zoukankan      html  css  js  c++  java
  • Codeforces Round #629 (Div. 3)【ABCDEF】(题解)

    目录

    涵盖知识点:思维、构造、树上倍增。

    比赛链接:传送门

    博客园目录好像不能用toc了???容我研究一下。。。

    A - Divisibility Problem

    题意: 给两个数(a,b),每次操作可以使(a=a+1),问最少几次操作后(a)(b)的倍数。
    题解:

    [ans=egin{cases} 0qquad a \% b=0 \ b-a qquad a<=b \ b-(a\% b)qquad a>b end{cases} ]

    Accept Code:

    #include <bits/stdc++.h>
    using namespace std;
    
    int main(){
        int t;
        cin>>t;
        while(t--){
            int a,b;
            cin>>a>>b;
            if(a%b==0){cout<<"0
    ";continue;}
            if(a<=b)cout<<b-a<<"
    ";
            else cout<<b-(a%b)<<"
    ";
        }
        return 0;
    }
    

    B - K-th Beautiful String

    题意: 长度为(n)的字符串包含(n-2)个a和(2)个b,求按照字典序排列的第(k)个。
    题解: 观察样例,左边的b的位置出现次数按照(1,2,3ldots)排列,确定后再确定右边的b的出现位置即可。
    Accept Code:

    #include <bits/stdc++.h>
    using namespace std;
    
    int main(){
        int t;
        cin>>t;
        while(t--){
            int n,k;
            cin>>n>>k;
            int l=1;
            while(k>l)k-=l,l++;
            l++;
            int r=k;
            for(int i=n;i>=1;i--){
                if(i==l||i==r)cout<<"b";
                else cout<<"a";
            }
            cout<<"
    ";
        }
        return 0;
    }
    

    C - Ternary XOR

    题意: 规定三进制下的运算(c = a odot b)(c_i = (a_i + b_i) \% 3),现给定(c),要求构造(a,b),并使得(max(a,b))尽可能小。
    题解: 第一个1分配给(a),后面的所有数字一律分配给(b)
    Accept Code:

    #include <bits/stdc++.h>
    using namespace std;
    
    int main(){
        int t;
        cin>>t;
        while(t--){
            int n;
            cin>>n;
            string s,a,b;
            cin>>s;
            bool flag=true;
            for(char i : s){
                if(flag) {
                    if (i == '0')a += '0', b += '0';
                    if (i == '1')a += '1', b += '0',flag=false;
                    if (i == '2')a += '1', b += '1';
                }else a+='0',b+=i;
            }
            cout<<a<<"
    "<<b<<"
    ";
        }
        return 0;
    }
    

    题意: (n)个动物围成一个环,现在要给动物上色,要求不能给相邻的不同动物上同一种颜色,问最少几种颜色可以满足条件。
    题解:

    1. 全同色,1种
    2. 不存在相邻的相同动物且为奇数,3种。(前面1,2间隔最后一个3)
    3. 其余情况两种。偶数(12121212)奇数(找组相邻相同的把12反向)

    画个图脑补一下就好了。
    Accept Code:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=2e5+10;
    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];
            a[0]=a[n];
            bool flag=true;
            for(int i=1;i<=n;i++){
                if(a[i]!=a[i-1]){
                    flag=false;
                    break;
                }
            }
            if(flag){
                cout<<"1
    ";
                for(int i=1;i<=n;i++)cout<<1<<" ";
                cout<<"
    ";
                continue;
            }
            int pos=0;
            for(int i=1;i<=n;i++){
                if(a[i]==a[i-1])
                    pos=i;
            }
            if(!pos&&(n&1)){
                cout<<"3
    ";
                for(int i=1;i<n;i++)cout<<i%2+1<<" ";
                cout<<"3
    ";
            }
            else{
                cout<<"2
    ";
                if(!(n&1)){
                    for(int i=1;i<=n;i++)cout<<i%2+1<<" ";
                    cout<<"
    ";
                }else{
                    for(int i=1;i<pos;i++)cout<<i%2+1<<" ";
                    for(int i=pos;i<=n;i++)cout<<2-i%2<<" ";
                    cout<<"
    ";
                }
            }
        }
        return 0;
    }
    

    E - Tree Queries

    题意: 给定一颗1为根的(n)顶点根树。对于(m)个询问,每个询问给(k)个点,问是否存在1出发的一条链使得这(k)个点距离链的距离小于1。
    题解:(k)个点里找深度最大的点为该链终点。扫描一下其他的点即可。暴力肯定不能过,倍增优化一下跳跃步长就行了。
    Accept Code:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=2e5+10;
    const int maxd=20;
    vector<int> edg[maxn];
    
    int fa[maxn][maxd];
    int deg[maxn];
    int vi[maxn];
    void bfs(int root){
        queue<int> q;
        deg[root]=0;
        fa[root][0]=root;
        q.push(root);
        while(!q.empty()){
            int u=q.front();
            q.pop();
            for(int i=1;i<maxd;i++){
                fa[u][i]=fa[fa[u][i-1]][i-1];
            }
            for(auto v:edg[u]){
                if(v==fa[u][0])continue;
                deg[v]=deg[u]+1;
                fa[v][0]=u;
                q.push(v);
            }
        }
    }
    int jump(int u,int det){
        for(int i=0;det;det>>=1,i++){
            if(det&1)u=fa[u][i];
        }
        return u;
    }
    int main(){
        int t;
        //cin>>t;
        //while(t--){
            int n,m;
            cin>>n>>m;
            for(int i=1,u,v;i<n;i++){
                cin>>u>>v;
                edg[u].push_back(v);
                edg[v].push_back(u);
            }
            bfs(1);
            while(m--){
                int k;
                cin>>k;
                for(int i=0;i<k;i++)cin>>vi[i];
                int x=1;
                for(int i=0;i<k;i++){
                    if(deg[fa[vi[i]][0]]>deg[x])x=fa[vi[i]][0];
                }
                //cout<<"x:"<<x<<"
    ";
                bool flag=true;
                for(int i=0;i<k;i++){
                    if(jump(x,deg[x]-deg[fa[vi[i]][0]])!=fa[vi[i]][0]){
                        flag=false;
                        break;
                    }
                }
                puts(flag?"YES":"NO");
            }
        //}
        return 0;
    }
    

    F - Make k Equal

    题意: (n)个数的数组(a),每次操作可以将某个最大值-1或者某个最小值+1.问操作几次使得至少存在(k)个相等的数字。
    题解: 我们假设(k)个相等的数字都是(i),只有先将所有小于(i)的数字变为(i-1)或者所有大于(i)的数字变为(i+1)才能够操作成(i)。所以我们只要把(a)排序后维护一个前缀和和一个后缀和。计算出前缀变成(i-1)和后缀变成(i+1)的次数就可以简单的计算出答案。扫描一遍取最小值即可。细节看代码(最大值会超过0x3f3f3f3f。。。挂了一发)
    Accept Code:

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int maxn=2e5+10;
    const ll inf=0x3f3f3f3f3f3f3f3f;
    int a[maxn];
    set<ll> st;
    map<ll,ll> mp;
    int main() {
        int n,k;
        cin>>n>>k;
        ll suml=0,sumr=0,cntl=0,cntr=n;
        for(int i=0;i<n;i++)cin>>a[i],sumr+=a[i],st.insert(a[i]),mp[a[i]]++;
        sort(a,a+n);
        ll res=inf;
        for(auto i:st){
            if(mp[i]>=k){
                cout<<"0
    ";
                return 0;
            }
            sumr-=mp[i]*i;
            cntr-=mp[i];
            ll cnt=k-mp[i];
            ll l=cntl*(i-1)-suml,r=sumr-cntr*(i+1);
            if(cntl>=cnt)res=min(res,l+cnt);
            if(cntr>=cnt)res=min(res,r+cnt);
            res=min(res,l+r+cnt);
            suml+=mp[i]*i;
            cntl+=mp[i];
        }
        cout<<res<<"
    ";
        return 0;
    }
    
  • 相关阅读:
    含有打印、统计DataGridView(1)
    数字金额转换大写人民币
    文件加密解密全解
    正则表达式之全部符号对照表
    C#程序集引入无效的解决方法
    TreeView 的简单实用
    Win7下用IIS发布网站
    C#做完一个网站怎么发布?
    c# 如何获取项目的根目录
    判断控件是否出现了滚动条
  • 原文地址:https://www.cnblogs.com/charles1999/p/12581503.html
Copyright © 2011-2022 走看看