1. 程式人生 > 實用技巧 >Codeforces Round #690 (Div. 3)(A->F)(F二分)

Codeforces Round #690 (Div. 3)(A->F)(F二分)

A:http://codeforces.com/contest/1462/problem/A

#include<iostream>
#include<cstring>
#include<map>
#include<stack>
#include<queue>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<string.h>
using namespace std;
typedef long long ll;
const int
maxn=2e4+10; const int inf=99999999; int a[maxn]; int main() { int t; cin>>t; while(t--) { int n; cin>>n; for(int i=1;i<=n;i++) cin>>a[i]; int cnt=0; int l=1; int ok=0; int md=n-1; while(1) {
if(cnt==n) break; if(!ok) { cout<<a[l]<<" "; l=l+md; md--; ok=1; } else { cout<<a[l]<<" "; l=l-md; md
--; ok=0; } cnt++; } cout<<endl; } }

B:http://codeforces.com/contest/1462/problem/B

題意:

給定一個字串,能否最多刪除一段連續的一段使得剩下的為“2020”

解析:

無非就六種情況,直接列一遍就好了

#include<iostream>
#include<cstring>
#include<map>
#include<stack>
#include<queue>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<string.h>
using namespace std;
typedef long long ll;
const int maxn=2e4+10;
const int inf=99999999;
int a[maxn];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        string s;
        cin>>s;
        int le=s.length();
        if(s=="2020")
        {
            cout<<"YES"<<endl;
        }
        else
        {
            if(s[0]=='2'&&s[1]=='0'&&s[2]=='2'&&s[3]=='0')
            {
                cout<<"YES"<<endl;
            }
            else if(s[0]=='2'&&s[1]=='0'&&s[2]=='2'&&s[le-1]=='0')
            {
                cout<<"YES"<<endl;
            }
            else if(s[0]=='2'&&s[1]=='0'&&s[le-2]=='2'&&s[le-1]=='0')
            {
                cout<<"YES"<<endl;
            }
            else if(s[0]=='2'&&s[le-3]=='0'&&s[le-2]=='2'&&s[le-1]=='0')
            {
                cout<<"YES"<<endl;
            }
            else if(s[le-4]=='2'&&s[le-3]=='0'&&s[le-2]=='2'&&s[le-1]=='0')
            {
                cout<<"YES"<<endl;
            }
            else 
                cout<<"NO"<<endl;
        }
    }
}

C:http://codeforces.com/contest/1462/problem/C

題意:

輸出最小的數位和等於x並且各個數位都不一樣的值

解析:

在紙上寫了一下,發現每一個存在的答案,都是從個位開始,數字越來越小。所以從9開始列舉即可。

#include<iostream>
#include<cstring>
#include<map>
#include<stack>
#include<queue>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<string.h>
using namespace std;
typedef long long ll;
const int maxn=2e4+10;
const int inf=99999999;
int a[maxn];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        if(n<=9)
        {
            cout<<n<<endl;continue;
        }
        if(n>45)
        {
            cout<<"-1"<<endl;continue;
        }
        int sum=0;
        int num[111];
        int tot=0,ok=0;
        int all=n;
        for(int i=9;i>=1;i--)
        {
            if(sum+i>n)
                continue;
            sum+=i;
            num[tot++]=i;
            if(sum==n)
            {
                ok=1;break;
            }
        }
        if(ok)
        {
            for(int i=tot-1;i>=0;i--)
                cout<<num[i];
            cout<<endl;
        }
        else
            cout<<"-1"<<endl;
    }
}

D:http://codeforces.com/contest/1462/problem/D

題意:

給出一個序列,每個數可以與左或右合併,這算一個操作。求使得所有數相同的最少運算元。

解析:

其實所謂所有數相同,就是把整個原數分成幾份,每一份加和相等。

所以先求出總和sum,列舉它的因子x,求一下每份和為x , sum / x的所需運算元,求個最小值即可。

#include<iostream>
#include<cstring>
#include<map>
#include<algorithm>
#include<stack>
#include<queue>
#include<cstdio>
#include<cmath>
#include<string.h>
using namespace std;
typedef long long ll;
const int maxn=3e3+10;
const int inf=99999999;
int a[maxn];
int n;
ll num[maxn];
ll sum=0;
int ac(int x)
{
    int all=sum/x;
    int ans=0;
    int cnt=0;
    int ok = 0 ;
    for(int i=1;i<=n;i++)
    {
        if(a[i]>x)
            return -1;
        if(a[i]==x&&ans<x&&ans>0)
            return -1;
        if(ans+a[i]==x)
        {
            if(ans>0)
                cnt++;
            ans=0;    
        }
        else if(ans+a[i]<x)
        {
            if(ans>0)
            cnt++;
            ans+=a[i];
            
        }
        else
        {
            return -1;
        }
    }
    return cnt;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        cin>>n;
        sum = 0 ;
        for(int i=1;i<=n;i++)
            cin>>a[i],sum+=a[i];
        int no=0;
        for(int i=1;i<n;i++)
        {
            if(a[i]!=a[i+1])
            {
                no=1;break;
            }
        }
        if(!no)
        {
            cout<<"0"<<endl;continue;
        }
//        cout<<ac(sum/2)<<endl;
        int ok = 0;
        int an=inf;
        for(int i=2;i*i<=sum;i++)
        {
            if(sum%i==0)
            {
                int md1=ac(i);
                int md2=ac(sum/i);
                if(md1!=-1)
                {
                    an=min(an,md1);
                //    cout<<i<<"--1"<<endl;
                    ok=1;
                }
                if(md2!=-1)
                {
                    an=min(an,md2);
                //    cout<<i<<"--2"<<endl;
                    ok=1;
                }    
            }
        }
        if(!ok)    
            cout<<n-1<<endl;//不存在,那麼全合併即可
        else
            cout<<an<<endl;
    }
}

E1:http://codeforces.com/contest/1462/problem/E1

題意:

求有多少組ai,aj,az,max(ai,aj,az)-min(ai,aj,az)<=2

解析:

由於這三個數並不需要挨著,所以順序無所謂。那麼可以先從小到大排個序。

列舉最小值ai,向右找到第一個aj-ai>2的位置,那麼i~j之間的數字隨便選兩個和ai組合就是一組答案,那麼答案就是C(j-i-1,2),累加即可。

#include<iostream>
#include<cstring>
#include<map>
#include<algorithm>
#include<stack>
#include<queue>
#include<cstdio>
#include<cmath>
#include<string.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
const int inf=99999999;
int a[maxn];
int n;
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        cin>>n;
        for(int i=1;i<=n;i++)
            cin>>a[i];
        sort(a+1,a+1+n);
        ll sum = 0 ;
        int r=2;
        for(int i=1;i<=n;i++)
        {
            while(a[r]-a[i]<=2&&r<=n)
                r++;
            ll cnt=(r-i-1);
            if(cnt>=2)
                sum+=cnt*(cnt-1)/2;
            
        }
        cout<<sum<<endl;
    }
}

E2:http://codeforces.com/contest/1462/problem/E2

與E1不同的是,所選數目以及最大差值可以自定義。

與E1思路相同,只是難點在求組合數這邊。考慮m只有100,那麼提前預處理一下組合數即可。

#include<iostream>
#include<cstring>
#include<map>
#include<algorithm>
#include<stack>
#include<queue>
#include<cstdio>
#include<cmath>
#include<string.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
const int inf=99999999;
const int mod=1e9+7;
int a[maxn];
int n,m,k;
int c[maxn][130];
void init()
{
    
    c[0][0]=1;
    c[1][0]=1;c[1][1]=1;
    for(int i=2;i<maxn;i++)
    {
        for(int j=0;j<=105&&j<=i;j++)
        {
            c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;
        }
    }
}
int main()
{
    int t;    
    init();
    scanf("%d",&t);
    while(t--)
    {
        cin>>n>>m>>k;
        for(int i=1;i<=n;i++)
            cin>>a[i];
        sort(a+1,a+1+n);
        ll sum=0;
        int r=1;
        for(int i=1;i<=n;i++)
        {
            while(a[r]-a[i]<=k&&r<=n)
                r++;            
            ll cnt=(r-i-1);
            if(cnt>=m-1)
            {
                sum=(sum+c[cnt][m-1])%mod;
            }
        }
        cout<<sum<<endl;
    }
}

F:http://codeforces.com/contest/1462/problem/F

題意:

給你n個線段,代表線段的左右端點,問最少刪幾條線段,使得剩下當中存在一個線段與所有剩下的所有線段都有交集。

解析:

考慮列舉每一條線段,求以此線段與所有線段都有交集,需要刪除的線段數。

那麼對於此線段[L,R],右端點小於L的,與它無交集,需要全刪掉。同理左端點大於R的線段,也需要都刪掉。

那麼剩下的問題,就是需要刪幾個了。

預存一下所有的L,R,放到x[],y[]裡面。對它們進行從小到大的排序。

對於當前列舉到的[L,R],求小於L的右端點不好求,那就先求>=L的,就是:lower_bound(y+1,y+1+n,a[i])-y; 再減1,就是小於L的了:lower_bound(y+1,y+1+n,a[i])-y-1;

然後求大於R的左端點,n-(upper_bound(x+1,x+1+n,b[i])-x)+1;

加起來,每次取最小即可。

#include<iostream>
#include<cstring>
#include<map>
#include<algorithm>
#include<stack>
#include<queue>
#include<cstdio>
#include<cmath>
#include<string.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+10;
const int inf=99999999;
const int mod=1e9+7;
int a[maxn],b[maxn],x[maxn],y[maxn];
int main()
{
    int t;    
    scanf("%d",&t);
    while(t--)
    {
        int n;
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            cin>>a[i]>>b[i];
            x[i]=a[i];
            y[i]=b[i];
        }
        sort(x+1,x+1+n);
        sort(y+1,y+1+n);
        ll minn = inf;
        for(int i=1;i<=n;i++)
        {
            ll l=lower_bound(y+1,y+1+n,a[i])-y-1;
            ll r=n-(upper_bound(x+1,x+1+n,b[i])-x)+1;
            minn=min(minn,l+r);
        }
        cout<<minn<<endl;
    }
}