Codeforces Round #767 Div. 2 Solution
Codeforces Round #767 Div. 2 Solution

Codeforces Round #767 Div. 2 Solution

A. Download More RAM

简单贪心,按a_i排序,每次k加上b_i,直到不能做为止。

B. GCD Arrays

题意:给定l、rk,存在数组内存有l~r的数,是否能进行k次操作后,满足数组内全部数的gcd>1,操作:选择两个数,删去数组中的它们,将他们的乘积放入数组。
发现两两相邻组合时为最优(产生的乘积都为偶数

同时发现两相邻数若存在就不能构成gcd>1,所以应满足k*2≥(r-l+1)
但是要判断两区间端点的奇偶性,若同时为奇数,则要满足最后一个剩余的数也能够进行操作。k=0 要特判。

#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define MAXN 1005
using namespace std;

void read(int &x){
    char c;while(((c=getchar())<'0'||c>'9')&&c!='-');x=0;int y=1;
    c=='-'?y=-1:x=c-'0';while((c=getchar())>='0'&&c<='9')x=(x<<1)+(x<<3)+c-'0';x*=y;
}
int T,l,r,k; 
int gcd(int x,int y){
    if(!y)return x;
    return gcd(y,x%y);
}
int main()
{
    read(T);
    while(T--){
        read(l),read(r),read(k);
        int t=(r-l)/2+((l%2)|(r%2)),ans=0;
        if(l==r)ans=l>1;
        else if(!k)ans=0;
        else if(k>=t)ans=1;
        puts(ans?"YES":"NO");
    }
}

C. Meximum Array

题意:存在一个a数组,每次可以取出前端连续的数,放到b中,但要满足:取出的连续的数mex是当前数组最大值,求每次取出的连续的数mex最大时结果(要求最终结果字典序最大)

维护一个f记录当前位置到最后的最大值,维护一个vis(其实就是),同时维护一个指针用于记录枚举时遇到的第一个桶的空位置(求mex)。
特判 数字不存在的情况。

#include <cstring>
#include <algorithm>
#define MAXN 200005
using namespace std;

int T,n,ans,Len;
int Pc[MAXN],vis[MAXN],f[MAXN],a[MAXN];

int main(){
    for(scanf("%d",&T);T;--T){
        scanf("%d",&n);
        for(int i=1;i<=n;++i)scanf("%d",&a[i]);
        f[n+1]=Len=0;
        for(int i=n;i;--i){
            f[i]=f[i+1],vis[a[i]]=1;
            while(vis[f[i]]!=0)
                f[i]=f[i]+1;
        }
        if(!vis[0]){
            printf("%d\\n",n);
            for(int i=1;i<=n;++i)printf("0 ");
            puts("");
            for(int i=1;i<=n;++i)vis[a[i]]=0;
            continue;
        }
        for(int i=1;i<=n;++i)vis[a[i]]=0;
        for(int i=1,j;i<=n;i=j+1){
            int nw=0;
            for(j=i;;++j){
                vis[a[j]]++;
                while(vis[nw])++nw;
                if(nw==f[i])break;
            }
            Pc[++Len]=nw;
            for(int k=i;k<=j;++k)--vis[a[k]];
        }
        printf("%d\\n",Len);
        for(int i=1;i<=Len;++i)printf("%d ",Pc[i]);
        puts("");
    }
}

D. Peculiar Movie Preferences

题意:有n个字符串,长度均为1~3,求是否能按顺序取出若干个,构成回文串

如果只有一个字符那么一定构成回文,容易发现只要判断是否有两个字符串能够组合构成回文即可。有两种情况,一种直接互为回文,一种删去前端或后端的一个字符后构成回文(abcba)。

维护哈希表,第一种直接求出正和反的哈希值判断即可,第二种需要前后两个方向枚举,依次维护两个哈希表来处理判断。
小细节,时间戳来替代数组初始化。

#include <string>
#include <cstring>
#include <algorithm>
#include <iostream>
#define MAXN 100005
using namespace std;

int T,n,t[50005],dfn,t2[20005];
string s,a[MAXN];
int main(){
    dfn=0;
    for(cin>>T;T;--T){
        cin>>n;++dfn;int tk=0;
        for(int i=1;i<=n;++i){
            cin>>s;a[i]=s;int tot=0,rev=0,tot2=0;
            for(int j=0;j<s.size();++j)tot=tot*27+s[j]-'a'+1;
            for(int j=s.size()-1;~j;--j)rev=rev*27+s[j]-'a'+1;
            t[tot]=dfn;
            if(t[rev]==dfn)tk=1;
            if(s.size()>=2){
                for(int j=s.size()-1;j;--j)tot2=tot2*27+s[j]-'a'+1;
                if(t[tot2]==dfn)tk=1;
            }
        }
        for(int i=n;i>=1;--i){
            int tot=0,rev=0,tot2=0;
            s=a[i];
            for(int j=0;j<s.size();++j)tot=tot*27+s[j]-'a'+1;
            for(int j=s.size()-1;~j;--j)rev=rev*27+s[j]-'a'+1;
            t2[tot]=dfn;
            if(t2[rev]==dfn)tk=1;
            if(s.size()>=2){
                for(int j=s.size()-2;~j;--j)tot2=tot2*27+s[j]-'a'+1;
                if(t2[tot2]==dfn)tk=1;
            }
        }
        puts(tk?"YES":"NO");
    }
}

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注