Codeforces Round #767 (Div. 2)

Posted on 2022-01-23 13:48  Capterlliar  阅读(45)  评论(0编辑  收藏  举报

感觉这次CD题比之前简单?

A. Download More RAM

题意:给n组数据和当前值k,k大于 ai 就可增加 bi ,问最后k最大值。

解:带水题,看代码即可。

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define maxx 200005
#define eps 0.00000001
#define inf 0x7fffffff
//#define int long long
int n,k;
int a[maxx],b[maxx];
signed main() {
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        for(int i=1;i<=n;i++)
            scanf("%d",&b[i]);
        vector<pair<int,int> > v;
        for(int i=1;i<=n;i++)
            v.push_back(make_pair(a[i],b[i]));
        sort(v.begin(),v.end());
        for(auto [ai,bi]:v){
            if(k>=ai)
                k+=bi;
            else
                break;
        }
        printf("%d\n",k);
    }
    return 0;
}
View Code

B. GCD Arrays

题意:给出一组连续的自然数,每次可以抓两个数把它们变成它们的乘积,问执行k次操作后整组数的gcd有没有可能不是1。

解:求一下不是1最少要执行几次。相邻的两个数两两互质,所以要使它们不再相邻至少执行n/2次。执行之后会有若干个偶数和可能留下的一个奇数,如果留下一个奇数加一次操作即可。

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define maxx 200005
#define eps 0.00000001
#define inf 0x7fffffff
//#define int long long
int n,k;
int l,r;
signed main() {
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d%d",&l,&r,&k);
        int temp=(r-l+1);
        int ans=0;
        if(temp==1){
            if(l==1)
                printf("NO\n");
            else
                printf("YES\n");
            continue;
        }
        else if(temp%2==0)
            ans=temp/2;
        else{
            if(l%2==0)
                ans=temp/2;
            else
                ans=(temp+1)/2;
        }
        if(k<ans)
            printf("NO\n");
        else
            printf("YES\n");
    }
    return 0;
}
View Code

C. Meximum Array

题意:给出[0,n]之间的n个数,每次选前k个取mex加入b,然后将k个数从原数组中删除。求字典序最大的b。

解:每次挑最大的mex加入b,并留下尽可能多的数。直接解法是每次求出最大mex,找到[0,mex]中数的最大位置pos,下一次从pos+1开始,然后把[1,pos]对应删除。实测会T。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define maxx 200005
#define eps 0.00000001
#define inf 0x7fffffff
//#define int long long
int n;
int a[maxx];
signed main() {
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        set<int> cnt[n+1];
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            cnt[a[i]].insert(i);
        }
        vector<int> ans;
        int pos=1;
        while(pos<=n){
            int mex=0;
            while(!cnt[mex].empty()) {
                pos=max(pos,*cnt[mex].begin());
                mex++;
            }
            ans.push_back(mex);
            for(int i=1;i<=pos;i++){
                cnt[a[i]].erase(i);
            }
            pos++;
        }
        printf("%d\n",ans.size());
        for(auto i:ans)
            printf("%d ",i);
        printf("\n");
    }
    return 0;
}
View Code

不加数据结构的话只能一个一个找过来求mex(加数据结构我也不会)。考虑能否直接判断这个位置已经取到最大的mex。当后续没有mex出现时,就可以开始找下一段的mex了。找下一段的mex需要把前面的删掉,因此还要保存现在出现的数,到时候再清空。

其实不太理解这玩意快在哪但它过了。

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define maxx 200005
#define eps 0.00000001
#define inf 0x7fffffff
//#define int long long
int n;
int a[maxx];
int cnt[maxx]={0};
signed main() {
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
            cnt[a[i]]++;
        }
        vector<int> ans;
        set<int> s;
        int mex=0;
        for(int i=1;i<=n;i++){
            cnt[a[i]]--;
            s.insert(a[i]);
            while(s.count(mex))
                mex++;
            if(cnt[mex]==0){
                ans.push_back(mex);
                mex=0;
                s.clear();
            }
        }
        printf("%d\n",ans.size());
        for(auto i:ans)
            printf("%d ",i);
        printf("\n");
    }
    return 0;
}
View Code

D. Peculiar Movie Preferences

题意:给出n个不超过3的字符串,问是否能够挑出几个按顺序拼成回文串。

解:这玩意比C简单,因为它每个长度都不超过3,变成了带分类讨论。

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define maxx 200005
#define eps 0.00000001
#define inf 0x7fffffff
//#define int long long
int n;
signed main() {
    int T;
    cin>>T;
    while(T--){
        cin>>n;
        map<string,int> m1;
        map<string,int> m2;
        string t[n+1];
        for(int i=1;i<=n;i++){
            cin>>t[i];
            m1[t[i]]=i;
            if(t[i].length()==3)
                m2[t[i].substr(1,2)]=i;
        }
        int flag=0;
        for(int i=1;i<=n;i++){
            int len=t[i].length();
            if(len==1){
                flag=1;
                break;
            }
            if(len==2) {
                string b = t[i];
                reverse(b.begin(), b.end());
                if (m1[b]||m2[b]>=i) {
                    flag = 1;
                    break;
                }
            }
            if(len==3){
                string b = t[i];
                reverse(b.begin(), b.end());
                if (m1[b]) {
                    flag = 1;
                    break;
                }
                b = t[i].substr(0,2);
                reverse(b.begin(), b.end());
                if (m1[b] >= i) {
                    flag = 1;
                    break;
                }
            }
        }
        if(flag)
            printf("YES\n");
        else
            printf("NO\n");
    }
    return 0;
}
View Code

E. Grid Xor

题意:有一个n*n的矩阵,n为偶数,将其每个格子的值替换为相邻四个格子值的异或和。现给出异或和矩阵,求原矩阵整个异或和。

解:一开始读假题了,但思路差不多。异或具有结合律,因此方法是找几个位置,使得这几个位置能覆盖整个矩阵,使得每个数字被覆盖奇数次,然后将这几个位置的值异或起来。现在考虑怎么找这些位置。这题读起来很熟,像紫书上奶牛翻砖块那题,就是中间那块不用翻。于是(很不要脸地)找了个奶牛刨地板的代码打表试图找规律,规律没找到,但发现第一行每一种可能都能解出解法,这个解是O(n)的。那当场跑一个吧。

打表代码出处

打表代码:

//#include<bits/stdc++.h>
//using namespace std;
//#define ll long long
//#define maxx 200005
//#define eps 0.00000001
//#define inf 0x7fffffff
////#define int long long
//int n;
//int a[1005][1005];
//signed main() {
//    int T;
//    scanf("%d",&T);
//    while(T--){
//        scanf("%d",&n);
//        for(int i=1;i<=n;i++)
//            for(int j=1;j<=n;j++)
//                scanf("%d",&a[i][j]);
//        int ans=0;
//        for(int i=1;i<=n;i+=2)
//            for(int j=1;j<=n;j++)
//                ans^=a[i][j];
//        printf("%d\n",ans);
//    }
//    return 0;
//}
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define ll long long
#define inf 1000000000
using namespace std;
int n,m,ed;
int xx[4]={0,0,1,-1},yy[4]={1,-1,0,0};
bool a[16][16],t[16][16],op[16][16];
void operate(int x,int y){
    op[x][y]=1;
    for(int k=0;k<4;k++)
    {
        int nowx=x+xx[k],nowy=y+yy[k];
        if(nowx<1||nowy<1||nowx>n||nowy>m)continue;
        t[nowx][nowy]^=1;
    }
}
void solve(int x){
    memset(op,0,sizeof(op));
    int tot=0;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            t[i][j]=a[i][j];
    for(int i=1;i<=m;i++)
        if((1<<(i-1))&x){
            operate(1,i);
        }
    for(int i=2;i<=n;i++)
        for(int j=1;j<=m;j++){
            if(t[i-1][j])
                operate(i,j);
        }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(t[i][j])return;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= m; j++)
            printf("%d ", op[i][j]);
        printf("\n");
    }
    printf("\n");
}
int main(){
    int x;
    scanf("%d",&x);
    for(int cnt=2;cnt<=x;cnt+=2) {
        printf("      %d\n",cnt);
        n = cnt;
        m = cnt;
        for (int i = 1; i <= n; i++)
            for (int j = 1; j <= m; j++)
                a[i][j] = 1;
        ed = (1 << m) - 1;
        solve(0);
//        for (int i = 0; i <= ed; i++)
//            solve(i);
    }
    return 0;
}
View Code

代码:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define maxx 1005
#define eps 0.00000001
#define inf 0x7fffffff
//#define int long long
int n;
int aa[maxx][maxx];
int xx[4]={0,0,1,-1},yy[4]={1,-1,0,0};
bool a[maxx][maxx],op[maxx][maxx];
void operate(int x,int y){
    op[x][y]=1;
    for(int k=0;k<4;k++){
        int nowx=x+xx[k],nowy=y+yy[k];
        if(nowx<1||nowy<1||nowx>n||nowy>n)continue;
        a[nowx][nowy]^=1;
    }
}
void solve(){
    for(int i=2;i<=n;i++)
        for(int j=1;j<=n;j++){
            if(a[i-1][j])
                operate(i,j);
        }
}
signed main() {
    int T;
    scanf("%d",&T);
    while(T--){
        memset(op,0,sizeof(op));
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                scanf("%d",&aa[i][j]);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                a[i][j]=1;
        solve();
        int ans=0;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                if(op[i][j])
                    ans^=aa[i][j];
        printf("%d\n",ans);
    }
    return 0;
}
View Code