zoukankan      html  css  js  c++  java
  • Codeforces Round #686 (Div. 3)

    Codeforces Round #686 (Div. 3)

    A. 给出一个错排。

    题解:整体左移一位即可。

    #include<bits/stdc++.h>
    
    using namespace std;
    
    int main(){
        int _;cin>>_;
        while(_--){
            int n;cin>>n;
            for(int i=1;i<n;++i)cout<<i+1<<" ";
            cout<<1<<endl;
        }
    
        return 0;
    }
    

    B. 找一个尽量小的出现一次的数字角标。

    题解:记录一下角标,从小往大贪心。

    #include<bits/stdc++.h>
    
    using namespace std;
    
    map<int,int>H;
    map<int,int>idx;
    
    int main(){
        int _;cin>>_;
        while(_--){
            H.clear();
            idx.clear();
            int n;cin>>n;
            for(int i=1;i<=n;++i){
                int x;cin>>x;
                ++H[x];
                idx[x]=i;
            }
    
            int flag=0;
            for(auto& p:H){
                if(p.second==1){
                    cout<<idx[p.first]<<endl;
                    flag=1;
                    break;
                }
            }
    
            if(!flag){
                cout<<"-1"<<endl;
            }
        }
    
        return 0;
    }
    

    C. 给你n个数的数组,你需要选定一个数,这个数不能碰,选择包含其他数的段进行删除。问最少删除几次能使得整个数组只剩下这个数字?

    题解:枚举数字,每次暴力往下一个跳就好了。

    #include<bits/stdc++.h>
    
    using namespace std;
    
    const int N = 200005;
    
    int n, a[N], vis[N], Next[N], last[N];
    
    int main(){
        int _;cin>>_;
        while(_--){
            cin>>n;
            for(int i=1;i<=n+1;++i){
                vis[i]=Next[i]=last[i]=-1;
            }
            for(int i=1;i<=n;++i)cin>>a[i];
            for(int i=n;i>=1;--i){
                Next[i]=last[a[i]];
                last[a[i]]=i;
            }
    
            int ans=n;
            for(int i=1;i<=n;++i){
                if(vis[i]==-1){
                    vis[i]=1;
                    int t=(i==1)?0:1;
                    int cur=i, nxt=Next[i];
                    int flag=cur;
                    while(nxt!=-1){
                        flag=max(flag,nxt);
                        vis[nxt]=1;
                        if(nxt!=cur+1)++t;
                        cur=nxt;
                        nxt=Next[nxt];
                    }
                    if(flag!=n)++t;
                    ans=min(ans,t);
                }
            }
    
            cout<<ans<<endl;
        }
    
        return 0;
    }
    

    D. 给你一个数,你要拆成多个数之积,并且每一个数都是后面一个数的因子。

    题解:质因数分解之后,最优构造取决于最大幂次。

    #include<bits/stdc++.h>
    
    using namespace std;
    
    typedef long long LL;
    
    const int N = 100005;
    
    bool isNot[N];
    
    int prime[N], tol;
    
    void sieve(){
        for(int i=2;i<=100000;++i){
            if(!isNot[i]){
                prime[++tol]=i;
                for(int j=2*i;j<=100000;j+=i){
                    isNot[j]=1;
                }
            }
        }
    }
    
    int main(){
        sieve();
        int _;cin>>_;
        while(_--){
            LL n;cin>>n;
            int mx=1;
            LL id=-1;
    
            for(int i=1;i<=tol;++i){
                if(1ll*prime[i]*prime[i]>n)break;
                int cnt=0;
                LL t=n;
                while(t%prime[i]==0){
                    ++cnt;
                    t/=prime[i];
                }
                if(cnt>mx){
                    mx=cnt;
                    id=prime[i];
                }
            }
    
            if(mx==1){
                cout<<"1"<<endl;
                cout<<n<<endl;
            }else{
                cout<<mx<<endl;
                for(int i=1;i<mx;++i){
                    cout<<id<<" ";
                    n/=id;
                }
                cout<<n<<endl;
            }
        }
    
        return 0;
    }
    

    E. 给你n个点的基环树,问你简单路径的条数。

    题解:首先考虑只有环的情况,结果显然是n*(n-1)。考虑一颗树上,每一个点,到本树另一个点的简单路径只有一条。所以,我们要考虑所有树的尺寸就好了。关于这个,我们可以在无向图拓扑排序的时候,用一个DSU维护每棵树的尺寸。

    #include<bits/stdc++.h>
    
    using namespace std;
    
    const int N = 200005;
    
    typedef long long LL;
    
    int n, deg[N], f[N], vis[N], sz[N];
    
    vector<int> G[N];
    
    inline int Find(int x){return x==f[x]?x:f[x]=Find(f[x]);}
    
    int main(){
        int _;scanf("%d",&_);
        while(_--){
            scanf("%d",&n);
            for(int i=1;i<=n;++i){
                G[i].clear();
                deg[i]=0;
                f[i]=i;
                vis[i]=0;
                sz[i]=1;
            }
            for(int i=1;i<=n;++i){
                int u, v;
                scanf("%d%d",&u,&v);
                G[u].push_back(v);
                G[v].push_back(u);
                ++deg[u];
                ++deg[v];
            }
    
            LL ans=1ll*n*(n-1);
    
            queue<int> q;
            for(int i=1;i<=n;++i){
                if(deg[i]==1){
                    q.push(i);
                    vis[i]=1;
                }
            }
    
            while(!q.empty()){
                int u=q.front();
                q.pop();
                for(auto& v:G[u]){
                    if(vis[v])continue;
                    int fu=Find(u);
                    int fv=Find(v);
                    if(f[fu]!=f[fv]){
                        sz[fu]+=sz[fv];
                        f[fv]=fu;
                    }
                    if(--deg[v]==1){
                        vis[v]=1;
                        q.push(v);
                    }
                }
            }
    
            for(int i=1;i<=n;++i){
                if(i==f[i]&&sz[i]>1){
                    ans-=1ll*sz[i]*(sz[i]-1)/2;
                }
            }
    
            cout<<ans<<endl;
        }
        return 0;
    }
    
    

    F. 给你n个数的数组,你现在要切这个数组为3段。第一段最大值等于第二段最小值,等于第三段最大值。

    题解:(来自I-wen Huang)。我们考虑这个相等的值,并且从大到小开始考虑。如果最大值超过3个,那直接白给。否则我们从大到小开始考虑的时候,记录一个边界(这里指大于这个值的最左和最右的边界,原因在于,在这个边界里面最大值肯定不是我们当前考虑的这个值)。这个时候,我们需要数出在这个边界中的,当前考虑的这个值的个数,且我们需要记录这个边界里,大于当前值的个数。如果大于等于这个值的个数,小于区间长度,那肯定不合法(最小值不是当前数)。这个时候,一个前缀和一个后缀都是小于等于当前值的。我们只需要考虑,三个等号是不是都可以取到就可以了。

    #include<bits/stdC++.h>
    
    using namespace std;
    
    const int N = 200005;
    
    int a[N], n;
    
    map<int, vector<int>> pos;
    
    int main(){
        int _;scanf("%d",&_);
        while(_--){
            pos.clear();
            scanf("%d",&n);
            for(int i=1;i<=n;++i){
                scanf("%d",a+i);
                pos[-a[i]].push_back(i);
            }
    
            int l=n+1, r=0;
            int flag=0;
            int gtr=0;
            for(auto& p:pos){
                int x=-p.first;
                vector<int> vec=p.second;
                if(l>n){
                    int sz=(int)vec.size();
                    if(sz>=3){
                        flag=1;
                        cout<<"YES"<<endl;
                        cout<<vec[1]-1<<" 1 "<<n-vec[1]<<endl;
                        break;
                    }
                }else{
                    int eql=0;
                    for(auto& v:vec){
                        if(v>=l&&v<=r){
                            ++eql;
                        }
                    }
    
                    if(r-l+1<=(gtr+eql)){
                        if(eql>0){
                            if(vec[0]<l&&vec.back()>r){
                                flag=1;
                                cout<<"YES"<<endl;
                                cout<<l-1<<" "<<r-l+1<<" "<<n-r<<endl;
                                break;
                            }
                        }else{
                            if(l-1>1&&a[l-1]==x&&vec[0]<l-1&&vec.back()>r){
                                flag=1;
                                cout<<"YES"<<endl;
                                cout<<l-2<<" "<<r-l+2<<" "<<n-r<<endl;
                                break;
                            }
    
                            if(r+1<n&&a[r+1]==x&&vec[0]<l&&vec.back()>r+1){
                                flag=1;
                                cout<<"YES"<<endl;
                                cout<<l-1<<" "<<r-l+2<<" "<<n-r-1<<endl;
                                break;
                            }
                        }
                    }
                }
    
                for(auto& v:vec){
                    l=min(l,v);
                    r=max(r,v);
                }
    
                gtr+=(int)vec.size();
            }
    
            if(!flag){
                cout<<"NO"<<endl;
            }
        }
        return 0;
    }
    
    
  • 相关阅读:
    存储器管理
    进程与线程
    进程间通信 IPC(Inter-Process Communication)
    进程的同步与互斥
    【bzoj4806~bzoj4808】炮车马后——象棋四连击
    【bzoj1013】[JSOI2008]球形空间产生器sphere
    【bzoj5427】最长上升子序列(贪心+LIS)
    NOIP2018没有什么新闻
    【bzoj3170】[Tjoi2013]松鼠聚会(数学题)
    【bzoj5170】Fable(树状数组)
  • 原文地址:https://www.cnblogs.com/JohnRan/p/14041305.html
Copyright © 2011-2022 走看看