• Codeforces Round #702 (Div. 3) 题解


    A

    分析:

    直接模拟,对于相邻的两个数,如果小的两倍还是比大的小,就乘2,同时贡献++。

    代码
    #pragma GCC optimize("O3")
    #include<bits/stdc++.h>
    
    using namespace std;
    #define SET0(a) memset(a,0,sizeof(a))
    #define FOR(i,a,b) for(int i=(a);i<=(b);i++)
    #define DWN(i,a,b) for(int i=(a);i>=(b);i--)
    #define INF 0x3f3f3f3f
    typedef long long ll;
    
    int a[55];
    int n;
    int cal(int idx){
        int maxv=max(a[idx],a[idx+1]);
        int minv=min(a[idx],a[idx+1]);
    
        int cnt=0;
        while(minv*2<maxv) {minv*=2;cnt++;}
    
        return cnt;
    
    }
    
    int main(){
        int T; cin>>T;
        while(T--){
            cin>>n;
            FOR(i,1,n) cin>>a[i];
            
            int cnt=0;
            FOR(i,1,n-1) cnt+=cal(i);
    
            cout<<cnt<<endl;
        }
        return 0;
    }
    

    B

    分析:

    统计出 (mod3) 三种余数的个数。然后对小于 (n/3) 个数的多少进行分类讨论:
    若个数为 (0) ,即最小的个数也是 (n/3) ,那么无需做任何操作。
    若个数为 (1) ,那么要让两个多的给那个少的补上,并统计贡献。
    若个数为 (2) ,那么要让多的给两个少的补上,并统计贡献。

    即:

            FOR(i,1,n){
                cin>>a[i];
                a[i]%=3;
                cnt[a[i]]++;
            }
            int minv=INF;
            FOR(i,0,2) minv=min(minv,cnt[i]);
    
            if(minv==n/3){
                cout<<0<<endl;
                continue;
            }
    
            int res=0;
    
            int cal=0;
    
            FOR(i,0,2){
                if(cnt[i]<n/3) cal++;
            }
    
            if(cal==1){
                int idx;
                FOR(i,0,2)
                    if(cnt[i]<n/3) idx=i;
                res+=cnt[(idx+2)%3]-n/3 + 2*(cnt[(idx+1)%3]-n/3);
            }
    
            else if(cal==2){
                int idx;
                FOR(i,0,2)
                    if(cnt[i]>n/3) idx=i;
    
                res+=n/3-cnt[(idx+1)%3] + 2*(n/3-cnt[(idx+2)%3]);
            }
    
            cout<<res<<endl;
    
    代码
    #pragma GCC optimize("O3")
    
    #include<bits/stdc++.h>
    using namespace std;
    #define SET0(a) memset(a,0,sizeof(a))
    #define FOR(i,a,b) for(int i=(a);i<=(b);i++)
    #define DWN(i,a,b) for(int i=(a);i>=(b);i--)
    #define INF 0x3f3f3f3f
    typedef long long ll;
    
    int a[30005];
    int cnt[3];
    int main(){
        int T; cin>>T;
        while(T--){
            SET0(cnt);
            int n; cin>>n;
            FOR(i,1,n){
                cin>>a[i];
                a[i]%=3;
                cnt[a[i]]++;
            }
            int minv=INF;
            FOR(i,0,2) minv=min(minv,cnt[i]);
    
            if(minv==n/3){
                cout<<0<<endl;
                continue;
            }
    
            int res=0;
    
            int cal=0;
    
            FOR(i,0,2){
                if(cnt[i]<n/3) cal++;
            }
    
            if(cal==1){
                int idx;
                FOR(i,0,2)
                    if(cnt[i]<n/3) idx=i;
                res+=cnt[(idx+2)%3]-n/3 + 2*(cnt[(idx+1)%3]-n/3);
            }
    
            else if(cal==2){
                int idx;
                FOR(i,0,2)
                    if(cnt[i]>n/3) idx=i;
    
                res+=n/3-cnt[(idx+1)%3] + 2*(n/3-cnt[(idx+2)%3]);
            }
    
            cout<<res<<endl;
    
        }
        return 0;
    }
    

    C

    分析:

    预处理出 ([1,1e4]) 的所有立方数,问题即转化为求 ([1,1e4]) 是否存在两个数满足它们的和为目标数。

    代码
    #pragma GCC optimize("O3")
    
    #include<bits/stdc++.h>
    using namespace std;
    #define SET0(a) memset(a,0,sizeof(a))
    #define FOR(i,a,b) for(int i=(a);i<=(b);i++)
    #define DWN(i,a,b) for(int i=(a);i>=(b);i--)
    #define INF 0x3f3f3f3f
    typedef long long ll;
    
    const int N=1e4+5;
    set<ll> rec;
    void init(){
        FOR(i,1,N)
            rec.insert((ll)i*i*i);
    }
    int main(){
        init();
        int T; cin>>T;
        while(T--){
            ll x; cin>>x;
    
            bool ok=0;
            for(auto i:rec){
                if(rec.find(x-i)!=rec.end()) ok=1;
            }
    
            if(ok) cout<<"YES"<<endl;
            else cout<<"NO"<<endl;
        }
        return 0;
    }
    

    D

    分析:

    分治,求出 ([1,n]) 中的最大值(根节点)所在下标 (root) ,然后继续处理 ([1,root-1])([root+1,n]) 的最大值(对应的下标即为 (root) 的左右节点),并且分别连边(建树)。

    建树后从根节点跑一遍dfs求出每个节点深度即可。

    代码
    #pragma GCC optimize("O3")
    
    #include<bits/stdc++.h>
    using namespace std;
    #define SET0(a) memset(a,0,sizeof(a))
    #define FOR(i,a,b) for(int i=(a);i<=(b);i++)
    #define DWN(i,a,b) for(int i=(a);i>=(b);i--)
    #define INF 0x3f3f3f3f
    typedef long long ll;
    
    const int N=205;
    
    int n;
    int a[N];
    struct node{
        int to,next;
    }e[N];
    int head[N],tot;
    void add(int u,int v){e[tot].to=v;e[tot].next=head[u];head[u]=tot++;}
    
    int d[N];
    
    int solve(int l,int r){
        if(l==r) return r;
        if(l>r) return -1;
    
        int root;
        FOR(i,l,r){
            if(a[i]==*max_element(a+l,a+1+r)){
                root=i;
                break;
            }
        }
    
        int ls=solve(l,root-1);
        int rs=solve(root+1,r);
    
        if(ls!=-1) add(root,ls);
        if(rs!=-1) add(root,rs);
    
        return root;
    }
    
    void dfs(int u,int deg){
        d[u]=deg;
        if(head[u]==-1) return;
    
        for(int i=head[u];~i;i=e[i].next){
            int go=e[i].to;
            dfs(go,deg+1);
        }
    }
    
    int main(){
        int T; cin>>T;
        while(T--){
            tot=0;
            memset(head,-1,sizeof head);
    
            cin>>n;
            FOR(i,1,n) cin>>a[i];
    
            solve(1,n);
    
            int root;
            FOR(i,1,n)
                if(a[i]==n) root=i;
    
            dfs(root,0); // for depth
    
            FOR(i,1,n) cout<<d[i]<<' ';
            cout<<endl;
        }
        return 0;
    }
    

    E

    分析:

    排序,找到一个断点 (idx) ,使得即便是 ([1,idx-1]) 的前缀和也比 a[idx] 小,那么 (idx) 之前的玩家必然无法获胜。最后记录一下 ([idx,n]) 的玩家编号即可。

    代码
    #pragma GCC optimize("O3")
    
    #include<bits/stdc++.h>
    using namespace std;
    #define SET0(a) memset(a,0,sizeof(a))
    #define FOR(i,a,b) for(int i=(a);i<=(b);i++)
    #define DWN(i,a,b) for(int i=(a);i>=(b);i--)
    #define INF 0x3f3f3f3f
    typedef long long ll;
    
    const int N=2e5+5;
    struct node{
        int id,v;
    }a[N];
    
    int b[N];
    int n;
    
    bool cmp(node a,node b){
        return a.v<b.v;
    }
    
    ll s[N];
    
    int main(){
        int T; cin>>T;
        while(T--){
            cin>>n;
            FOR(i,1,n){
                cin>>a[i].v;
                a[i].id=i;
            }
    
            sort(a+1,a+1+n,cmp);
    
            FOR(i,1,n){
                s[i]=s[i-1]+a[i].v;
            }
    
            int idx=1;
            DWN(i,n,1){
                if(s[i-1]<a[i].v){
                    idx=i;
                    break;
                }
            }
    
            cout<<n-idx+1<<endl;
    
            int cnt=0;
            FOR(i,idx,n) b[cnt++]=a[i].id;
    
            sort(b,b+cnt);
    
            FOR(i,0,cnt-1) cout<<b[i]<<' ';
            cout<<endl;
        }
        return 0;
    }
    

    F

    分析:

    记录一下每个数对应的个数,然后从大到小进行排序,枚举断点 (i)([1,i]) 的数表示不需要删到 (0)([i+1,tot]) 的则全部删到 (0)。最后统计贡献并求最小值。

    代码
    #pragma GCC optimize("O3")
    
    #include<bits/stdc++.h>
    using namespace std;
    #define SET0(a) memset(a,0,sizeof(a))
    #define FOR(i,a,b) for(int i=(a);i<=(b);i++)
    #define DWN(i,a,b) for(int i=(a);i>=(b);i--)
    #define INF 0x3f3f3f3f
    typedef long long ll;
    
    const int N=2e5+5;
    int n;
    int buc[N];
    
    int main(){
        int T; cin>>T;
        while(T--){
            map<int,int> f;
            cin>>n;
            FOR(i,1,n){
                int k; cin>>k;
                ++f[k];
            }
            
            int tot=0;
            for(auto i:f)
                buc[++tot]=i.second;
            
            sort(buc+1,buc+1+tot,greater<int>());
    
            int ans=INF;
            FOR(i,1,tot)
                ans=min(ans,n-i*buc[i]);
            
            cout<<ans<<endl;
        }
        return 0;
    }
    
  • 相关阅读:
    c++基础_矩阵乘法
    c++基础_字符串对比
    c++基础_时间转换
    c++基础_特殊回文数
    c++基础_回文数
    c++基础_特殊的数字
    c++基础_杨辉三角形
    c++基础_字母图形
    c++基础_01字串
    java 常用集合类型--以及其特性
  • 原文地址:https://www.cnblogs.com/Tenshi/p/14408558.html
Copyright © 2020-2023  润新知