Codeforces Round #658 (Div. 2)总结

感受:一开始被b给唬住了,看着是个博弈,结果越看越像水题,浪费了不少时间,c2没想到 O ( n ) O(n) O(n)做法,勉强打了个暴力交的c1,然后快结束了才看的D,也想到01背包了,没时间了。得出一个教训,每次遇到自己不会的题的时候往下看一道题,说不定就有会做的,可能太往下的题不在知识范围,那就不看。不能在一个题上吊死。。就像这个D最后一共才思考了七八分钟。。要打代码结果结束了。

A题

题目大意:

在a中找一个b的最短子序列。

思路:

都说最短了,就是1呗。
代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const int N=1e3+10;
int a[N],b[N];
int main()
{
    
    
    int t;
    cin>>t;
    while(t--)
    {
    
    
        map<int,int>f;
        int n,m;
        cin>>n>>m;
        for(int i=1;i<=n;i++) cin>>a[i],f[a[i]]=1;
        for(int i=1;i<=m;i++) cin>>b[i];
        int flag=0;
        for(int i=1;i<=m;i++)
        {
    
    
            if(f[b[i]])
            {
    
    
                flag=1;
                cout<<"YES"<<endl;
                cout<<1<<' '<<b[i]<<endl;
                break;
            }
        }
        if(!flag) cout<<"NO"<<endl;
    }
    return 0;
}

B题

题目大意:

两个人拿石子,谁最先没石子可以拿谁输。

思路:

小小分析可以发现,谁拿最后一堆谁赢。那么每个人的最优做法就是让自己拿最后一堆。为了让下一步自己先手,所以遇到不是1的石子堆时,可以拿到只剩下1个石子,然后让对方拿,这样还可以保证自己的先手,但如果下一个是1的话,那么当前这一堆就要全拿掉,所以怎么选我们不用管他俩,他们自己精明得很,我们只需算出谁能第一个保证先手,先手的那个一定会很精明的让自己赢。就是算出前面有几个1来就行了。特判一个全是1的情况。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const int N=1e5+10;
int a[N];
int main()
{
    
    
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    int t;
    cin>>t;
    while(t--)
    {
    
    
        int n,num=0;
        cin>>n;
        for(int i=1;i<=n;i++)
        {
    
    
            cin>>a[i];
            if(a[i]==1) num++;
        }
        if(n==1)
        {
    
    
            cout<<"First"<<endl;
            continue;
        }
        if(num==n)
        {
    
    
            if(n&1) cout<<"First"<<endl;
            else cout<<"Second"<<endl;
            continue;
        }
        int flag=1;
        int now=1;
        while(a[now]==1&&now<=n)
        {
    
    
            flag^=1;
            now++;
        }
        if(flag) cout<<"First"<<endl;
        else cout<<"Second"<<endl;
    }
    return 0;
}

C题

题目大意:

给你a和b两个01串,你可以执行这个操作,选定a的前缀反转每个字符,然后把这个前缀倒过来。用最多2n次操作把a变成b。

思路:

每次都反转再倒过来太麻烦了,索性直接把a变成单一字符,最多n次操作,然后再把这个单一字符a变成b,最多n次操作。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const int N=1e5+10;
char a[N],b[N];
int ans[N<<1];
int main()
{
    
    
    int t;
    cin>>t;
    while(t--)
    {
    
    
        int n,cnt=0;
        cin>>n;
        cin>>(a+1);
        cin>>(b+1);
        for(int i=1;i<n;i++)
        {
    
    
            if(a[i]!=a[i+1])
            {
    
    
                ans[++cnt]=i;
            }
        }
        if(a[n]!='0') ans[++cnt]=n;
        int r=n;
        int flag=0;
        while(r>=1)
        {
    
    
            if(b[r]-'0'==flag) r--;
            else
            {
    
    
                ans[++cnt]=r;
                flag^=1;
            }
        }
        cout<<cnt<<' ';
        for(int i=1;i<=cnt;i++) cout<<ans[i]<<' ';
        cout<<endl;
    }
    return 0;
}

D题

题目大意:

就是两个数组每次取最小的加入到一个序列中,问能否从最后的序列得到原始的两个数组。

思路:

稍微分析一下发现,这一个序列可以分段,从数i开始找直接遇到一个大于它的为止,这算一段,然后把这些段任意组合,能否组合出这两个数组。那么我们就可以把这些段按01背包的方式进行组合,问最后能否有一个容量为n的背包组合出一个长度为n的数组。能的话就是yes,否则no

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const int N=2e4+10;
int a[N],dp[N],d[N];
int main()
{
    
    
    int t;
    cin>>t;
    while(t--)
    {
    
    
        memset(dp,0,sizeof(dp));
        int n;
        cin>>n;
        for(int i=1;i<=2*n;i++) cin>>a[i];
        int cnt=0,now=1;
        while(now<=2*n)
        {
    
    
            int len=1,in=now;
            while(a[in]>a[now+1]&&now<2*n) now++,len++;
            d[++cnt]=len;
            //cout<<len<<endl;
            now++;
        }
        for(int i=1;i<=cnt;i++)
            for(int j=n;j>=d[i];j--)
            dp[j]=max(dp[j],dp[j-d[i]]+d[i]);
        if(dp[n]==n) cout<<"YES"<<endl;
        else cout<<"NO"<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/amazingee/article/details/107519213