Codeforces Round#470

CF948A Protect Sheep(模拟)

没看到输出“Yes”卡了二十分钟【再见】

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define mod 1000000007
#define N 600
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x*f;
}
int n,m;
char mp[N][N];
int main(){
//  freopen("a.in","r",stdin);
    n=read();m=read();
    for(int i=1;i<=n;++i)
        scanf("%s",mp[i]+1);
    for(int i=1;i<=n;++i)
        for(int j=1;j<m;++j)
            if((mp[i][j]=='S'&&mp[i][j+1]=='W')||(mp[i][j]=='W'&&mp[i][j+1]=='S')){puts("No");return 0;}
    for(int j=1;j<=m;++j)
        for(int i=1;i<n;++i)
            if((mp[i][j]=='S'&&mp[i+1][j]=='W')||(mp[i][j]=='W'&&mp[i+1][j]=='S')){puts("No");return 0;}
    puts("Yes");
    for(int i=1;i<=n;++i){
        for(int j=1;j<=m;++j) if(mp[i][j]=='.') mp[i][j]='D';
        puts(mp[i]+1);
    }return 0;
}

CF923A Primal Sport(线性素数筛,数学)

再一次卡了半天【再见】
我们可以先O(n)处理出P(n),表示n的最大质因数。
然后我们发现 xi 的取值范围为 xi+1>=xi>xi+1P(xi+1) 。于是我们可以枚举x1,然后O(1)得到最小的x0.
在讨论中看到,其实可以做到 O(n)+O(logn)
令Q(n)=n/P(n).则 x0=x1P(x1)+1=x1(11/Q(x1)+1
从小到大枚举x1的话,显然当Q(x1)=2时再大的x1就不会使得x0的值就更小了。而Q(n)=2,说明n=2*P(n),而质数分布大概是log的,所以我们最多枚举log个x1就可以了。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define mod 1000000007
#define N 1000010
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x*f;
}
int n,ans=inf,tot=0,prime[N],a[N];
bool notprime[N];
void getprime(){
    notprime[1]=1;
    for(int i=2;i<=1000000;++i){
        if(!notprime[i]) prime[++tot]=i,a[i]=i;
        for(int j=1;prime[j]*i<=1000000;++j){
            notprime[prime[j]*i]=1;a[prime[j]*i]=a[i];
            if(i%prime[j]==0) break;
        }
    }
}
int main(){
//  freopen("a.in","r",stdin);
    int n=read(),x=n,mx=0;getprime();
    for(int i=2;i*i<=n;++i){
        if(x%i) continue;
        while(x%i==0) x/=i;
        mx=i;
    }if(x!=1) mx=x;
    for(int i=n-mx+1;i<=n;++i){
        if(!notprime[i]) continue;
        ans=min(ans,i-a[i]+1);
    }printf("%d\n",ans);
    return 0;
}

CF923B Producing Snow(树状数组+二分/平衡树)

大概就是给t数组做个前缀和,然后二分一下这堆雪在那一天化没,记录对答案的贡献。Visjiao巨佬用splay直接踩了过去。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 100010
inline char gc(){
    static char buf[1<<16],*S,*T;
    if(S==T){T=(S=buf)+fread(buf,1,1<<16,stdin);if(S==T) return EOF;}
    return *S++;
}
inline int read(){
    int x=0,f=1;char ch=gc();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
    return x*f;
}
int n,a[N],t[N],c[N];
ll sum[N],ans[N];
inline void add(int x,int val){
    for(;x<=n;x+=x&-x) c[x]+=val;
}
inline int ask(int x){
    int res=0;for(;x;x-=x&-x) res+=c[x];return res;
}
int main(){
//  freopen("a.in","r",stdin);
    n=read();
    for(int i=1;i<=n;++i) a[i]=read();
    for(int i=1;i<=n;++i) t[i]=read(),sum[i]=sum[i-1]+t[i];
    for(int i=1;i<=n;++i){
        ll x=a[i]+sum[i-1];
        int cnt=upper_bound(sum+1,sum+n+1,x)-sum;//i~cnt-1
        if(i!=cnt) add(i,1),add(cnt,-1);
        ans[cnt]+=x-sum[cnt-1];
    }for(int i=1;i<=n;++i) printf("%I64d ",ans[i]+(ll)ask(i)*t[i]);
    return 0;
}

CF923C Perfect Security(贪心+Trie)

复杂度 O(nlogw)

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 300010
inline char gc(){
    static char buf[1<<16],*S,*T;
    if(S==T){T=(S=buf)+fread(buf,1,1<<16,stdin);if(S==T) return EOF;}
    return *S++;
}
inline int read(){
    int x=0,f=1;char ch=gc();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
    return x*f;
}
int n,a[N],son[N*30][2],cnt[N*30],bin[32],rt=1,tot=1,ans;
inline void ins(int x){
    int p=rt;cnt[rt]++;
    for(int i=29;i>=0;--i){
        int op=x>>i&1;
        if(!son[p][op]) son[p][op]=++tot;p=son[p][op];
        cnt[p]++; 
    }
}
inline void ask(int x){
    int p=rt;
    for(int i=29;i>=0;--i){
        int op=x>>i&1;
        if(!son[p][op]||!cnt[son[p][op]]) ans|=bin[i],p=son[p][op^1];
        else p=son[p][op];cnt[p]--;
    }
}
int main(){
//  freopen("a.in","r",stdin);
    n=read();bin[0]=1;
    for(int i=1;i<=n;++i) a[i]=read();
    for(int i=1;i<=30;++i) bin[i]=bin[i-1]<<1;
    for(int i=1;i<=n;++i){
        int x=read();ins(x);
    }for(int i=1;i<=n;++i){
        ans=0;ask(a[i]);printf("%d ",ans);
    }return 0;
}

CF923D Picking Strings(手玩题)

通过手玩发现B和C可以互换,于是把C都换成B。然后我们的操作就是
A->BB
AB->B
B->AB
AAA->empty string
于是一个B的前面我们可以加减若干A,于是我们只需考虑B的个数以及末尾A的个数。
分三类:
1、末尾A个数相等,B1>B2且差为偶数则ok
2、原串有B,A1>A2,则(A1-A2)%3若还剩,就需要换出一个BB,然后转1
3、原串无B,则A1必须大于A2,并换出一个BB。
赛后A题gg(赛后也fst呢【逃】)

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 100010
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x*f;
}
int n,m,sum1[N],sum2[N],Q,la1[N],la2[N];
char s1[N],s2[N],ans[N];
int main(){
//  freopen("a.in","r",stdin);
    scanf("%s",s1+1);scanf("%s",s2+1);
    n=strlen(s1+1);m=strlen(s2+1);Q=read();
    for(int i=1;i<=n;++i){
        sum1[i]=sum1[i-1]+(s1[i]!='A');
        if(s1[i]=='A') la1[i]=la1[i-1]+1;else la1[i]=0;
    }
    for(int i=1;i<=m;++i){
        sum2[i]=sum2[i-1]+(s2[i]!='A');
        if(s2[i]=='A') la2[i]=la2[i-1]+1;else la2[i]=0;
    }
    for(int i=1;i<=Q;++i){
        int l1=read(),r1=read(),l2=read(),r2=read();
        int cnt1=sum1[r1]-sum1[l1-1],cnt2=sum2[r2]-sum2[l2-1];
        int num1=min(la1[r1],r1-l1+1),num2=min(la2[r2],r2-l2+1);
        if(num1<num2){ans[i]='0';continue;}
        if(!cnt1&&cnt2){
            if(num1==num2){ans[i]='0';continue;}
            cnt1+=2;
        }
        else if((num1-num2)%3) cnt1+=2;
        if(cnt1>cnt2||(cnt2-cnt1)&1) {ans[i]='0';continue;}
        ans[i]='1';
    }puts(ans+1);
    return 0;
}

总结:反向做题简直日神仙。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值