• Codeforces Round #658 (Div. 2)【ABCD】(题解)


    涵盖知识点:思维、dp

    比赛链接:传送门

    A - Common Subsequence

    题意: 找串(a,b)的最短公共子序列
    题解: 找一个相同的字母即可。若全不同则不存在。
    Accept Code:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=1010;
    int a[maxn],b[maxn];
    int main(){
        int t;cin>>t;
        while(t--){
            int n,m;
            cin>>n>>m;
            memset(a,0,sizeof a);
            for(int i=0;i<n;i++){
                int x;
                cin>>x;
                a[x]=1;
            }
            int ans=0;
            for(int i=0;i<m;i++){
                int x;
                cin>>x;
                if(a[x]==1){
                    ans=x;
                }
            }
            if(ans){
                cout<<"YES
    "<<1<<" "<<ans<<"
    ";
            }
            else cout<<"NO
    ";
        }
        return 0;
    }
    

    B - Sequential Nim

    题意: 博弈,每个人可以从含有石子的序号最小的堆中拿走任意正数个石子。
    题解: 一般情况下先手必胜,可以每堆都拿到剩1个,然后最后一堆一次性拿完。如果中间存在1个的堆,那么可以一次性拿完前一堆,另一人只能拿完那一堆,回到正常的状态。但是如果开头存在奇数个1个的堆,那么先后手交换。特判一下所有堆都是1的情况。
    Accept Code:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=1e5+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];
            }
            int cnt=0;
            for(int i=1;i<=n;i++){
                if(a[i]==1)cnt++;
                else break;
            }
            if(cnt==n)cnt++;
            puts(cnt&1?"Second":"First");
        }
        return 0;
    }
    

    C2 - Prefix Flip (Hard Version)

    题意: 给定两个二进制串(a,b)。每次选择一个数字,将(a)的前缀各位取反后再倒序。要求在(2n)次操作后将(a)变为(b)
    题解: 先最多花费(n)次将(a)所有位变为相同数字,再从后往前确定每一位的数字。若对应位不同,则对其包含在内的所有前缀进行翻转。
    Accept Code:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=1e5+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];
            }
            int cnt=0;
            for(int i=1;i<=n;i++){
                if(a[i]==1)cnt++;
                else break;
            }
            if(cnt==n)cnt++;
            puts(cnt&1?"Second":"First");
        }
        return 0;
    }
    

    D - Unmerge

    题意: 给定(2n)长度的数组(p),问是否可能为两个长度为(n)(a,b)合并而成,合并规则大概是依次从(a,b)中第一个未被选用的位置中选择一个较大的数字加入(p)
    题解: 观察(p),按照向右的第一个比当前段最大值大的值进行分段。以([3,2,6,1,5,7,8,4])为例,将其分为([3,2],[6,1,5],[7],[8,4])四段。可以很明显的看出,我们只有将这些段任意组合的结果才可以得到最后的串。所以我们只要判断这些段能否组成长度为(n)即可。dp一下就可以了。
    Accept Code:

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=4010;
    vector<int> idx;
    int dp[maxn],v[maxn];
    int main(){
        int t;cin>>t;
        while(t--){
            idx.clear();
            memset(dp,0,sizeof dp);
            memset(v,0,sizeof v);
            int n;
            cin>>n;
            int mx=0;
            for(int i=0,a;i<2*n;i++){
                cin>>a;
                if(a>mx){
                    mx=a;
                    idx.push_back(i);
                }
            }
            for(int i=0;i<idx.size()-1;i++){
                v[i]=idx[i+1]-idx[i];
            }
            for(int i=0;i<idx.size();i++){
                for(int j=n;j>=v[i];j--){
                    dp[j]=max(dp[j],dp[j-v[i]]+v[i]);
                }
            }
            puts(dp[n]==n?"YES":"NO");
        }
        return 0;
    }
    
  • 相关阅读:
    板子的配置
    检查点队列中未提交的数据块如何管理会减少内存使用
    js求月末new Date(year,month,0)
    js 截取字符串
    es6 x,y 互换值
    android x86 9.0r2 install guide 旧笔记本改造机顶盒
    Linux中常用命令
    在pyspark中调用scala/java代码
    Linux中安装sbt
    IDEA中手动引入JAR包
  • 原文地址:https://www.cnblogs.com/charles1999/p/13370528.html
Copyright © 2020-2023  润新知