zoukankan      html  css  js  c++  java
  • 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;
        }
    }
  • 相关阅读:
    我的软考之路
    VB成员函数集锦
    关于软件维护问题的几点思考
    element样式调整用到的东西
    JS实现旋转的魔方
    关于echarts 重绘/图表切换/数据清空
    CSS3 @keyframes 实现匀速旋转魔方(搬运工)
    在vue的js文件引入自定义js文件
    记录 vue+element树节点的标注
    echarts 设置图例文本不可点击
  • 原文地址:https://www.cnblogs.com/liyexin/p/14152120.html
Copyright © 2011-2022 走看看