1305C,1503A 构造,1295C ,446A

92 阅读1分钟

1305C - Kuroni and Impossible Calculation 抽屉原理

 推了三页式子还没有推出来之后去看题解直接绷不住了,一看抽屉原理就直接裂开了,确实,m只有1000,如果n>m的话那么一定有两个数是同余的那么这两个数会产生一个0,所以答案就是0,所以只需要管n<=m的情况即可,也就1000*1000的复杂度

C. Kuroni and Impossible Calculation(抽屉原理)_zjj0624的博客-CSDN博客

ll n,m,a[200005];
int main(){
    scanf("%lld%lld",&n,&m);
    if(n>m){
        printf("0\n");
        return 0;
    }
    for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    ll ans=1;
    for(int i=1;i<=n;i++)
    for(int j=i+1;j<=n;j++)
        ans=ans*abs(a[i]-a[j])%m;
    printf("%lld\n",ans);
    return 0;
}

1503A - Balance the Bits 构造

右括号一定是要小于等于左括号的,s[i]=1的时候不会影响ab中左右括号的差,但是0会影响,为了修复这个影响必然还需要一个0才可以,所以0的个数要是偶数才行,这样前一半的1都为'('后一半是')',然后s[i]==0时交替放就可以,比如奇数时a[i]='(',b[i]=')',偶数时再反过来就可以了

codeforces1503A. Balance the Bits_二分抄代码的博客-CSDN博客

ll t,n,a1[200005],a0[200005];
char s[200005],aa[200005],bb[200005];
int main(){
    scanf("%lld",&t);
    while(t--){
        scanf("%lld%s",&n,s+1);
        if(s[1]!='1'||s[n]!='1'){printf("NO\n");continue;}
        ll id1=0,id0=0;
        for(int i=1;i<=n;i++)
            if(s[i]=='0') a0[++id0]=i;
            else a1[++id1]=i;
        if(id0&1){printf("NO\n");continue;}
        for(int i=1;i<=id1;i++){
            if(i<=id1/2) aa[a1[i]]='(',bb[a1[i]]='(';
            else aa[a1[i]]=')',bb[a1[i]]=')';
        }
        for(int i=1;i<=id0;i++){
            if(i&1) aa[a0[i]]='(',bb[a0[i]]=')';
            else aa[a0[i]]=')',bb[a0[i]]='(';
        }
        printf("YES\n");
        for(int i=1;i<=n;i++) printf("%c",aa[i]);
        printf("\n");
        for(int i=1;i<=n;i++) printf("%c",bb[i]);
        printf("\n");
    }
    return 0;
}

1295C - Obtain The String

把每个字母的下标都存到vector中,遍历t数组如果t[i]的vector有值且有大于ind(记录遍历的最小坐标)的值那就更新ind,否则ind=t[i]vector的最小值重新开始

ll T,a[30];
vector<ll>v[30];
char s[100005],t[100005];
int main(){
    scanf("%lld",&T);
    while(T--){
        scanf("%s%s",s+1,t+1);
        ll n=strlen(s+1),m=strlen(t+1);
        for(int i=0;i<26;i++) v[i].clear(),a[i]=0;
        for(int i=1;i<=n;i++)
            v[s[i]-'a'].push_back(i);
        ll ans=1,ind=0;
        for(int i=1;i<=m;i++){
            if(v[t[i]-'a'].size()>a[t[i]-'a']){
                ll id=upper_bound(v[t[i]-'a'].begin(),v[t[i]-'a'].end(),ind)-v[t[i]-'a'].begin();
                //ll res=v[t[i]-'a'][a[t[i]-'a']];
                //cout<<res<<" "<<ind<<" "<<a[t[i]-'a']<<" "<<v[t[i]-'a'][a[t[i]-'a']]<<" "<<t[i]<<endl;
                //a[t[i]-'a']++;
                if(id!=v[t[i]-'a'].size()){ind=v[t[i]-'a'][id];}
                else{
                   // cout<<res<<" "<<ind<<" "<<a['s'-'a']<<endl;
                    ans++;ind=v[t[i]-'a'][0];
                   // for(int j=0;j<26;j++) a[j]=0;
                    //a[t[i]-'a']=1;
                }
            }
            else{
                if(v[t[i]-'a'].size()<=0){ans=-1;break;}
                //cout<<ind<<endl;
                ans++;ind=v[t[i]-'a'][0];
                //for(int j=0;j<26;j++) a[j]=0;
                //a[t[i]-'a']=1;
            }
        }
        printf("%lld\n",ans);
    }
    return 0;
}

446A - DZY Loves Sequences

这题看数据瞎搞过的,,,

求出差分数组b和b[i]的坐标c[b[i]],答案一定是在c[b[i-1]]到c[b[i+1]]-1的这段距离中,也有可能是c[b[i-1]]到c[b[i]]-1或者是c[b[i]]到c[b[i+1]]-1的这段距离中,注意下细节和满足条件就可以了

ll n,a[100005],c[100005],b[100005];
int main(){
    scanf("%lld",&n);
    for(int i=1;i<=n;i++) scanf("%lld",&a[i]),b[i]=a[i]-a[i-1];
    ll cnt=0,ans=1;
    for(int i=1;i<=n;i++)
        if(b[i]<=0) c[++cnt]=i;
    c[0]=1;c[cnt+1]=n+1;b[n+1]=1e9;
    if(cnt==0){
        printf("%lld\n",n);
        return 0;
    }
    for(int i=1;i<=cnt;i++){
        //cout<<c[i]<<endl;
        if(c[i]==2&&b[c[i]+1]>0){ans=max(ans,c[i+1]-c[i-1]);continue;}
        if(a[c[i]-1]<a[c[i]+1]-1||c[i]>2&&a[c[i]-2]<a[c[i]]-1){ans=max(ans,c[i+1]-c[i-1]);}
        else ans=max(ans,max(c[i]-c[i-1]+1,c[i+1]-c[i]+1));
    }
    printf("%lld\n",ans);
    return 0;
}

其实这题最好的方法是dp l[i]为以i结尾可以构造的最长序列,r[i]是以i开头可以构造的最长序列, ans=max(ans,l[i-1]+1,r[i+1]+1,l[i-1]+1+r[i+1]);

ll n,a[100005],l[100005],r[100005];
int main(){
    scanf("%lld",&n);
    for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    l[1]=r[n]=1;
    for(int i=2;i<=n;i++)
        if(a[i]>a[i-1]) l[i]=l[i-1]+1;
    else l[i]=1;
    for(int i=n-1;i>=1;i--)
        if(a[i]<a[i+1]) r[i]=r[i+1]+1;
    else r[i]=1;
    ll ans=1;
    for(int i=1;i<=n;i++){
        ans=max({ans,l[i-1]+1,r[i+1]+1});
        if(a[i-1]<a[i+1]-1) ans=max(ans,l[i-1]+1+r[i+1]);
    }
    printf("%lld\n",ans);
    return 0;
}