CF551

CF551A

水题,只要知道比他大的人数,二分即可。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inl inline
#define endl '\n'
#define int ll
#define gc cin.get
#define pc cout.put
const int N=2e5+5;
const int M=1e7+5;
const int inf=0x3f3f3f3f3f3f3f3f;
const int mod=1e4+7;
inl int read(){
    int x=0,f=1;char c=gc();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc();}
    while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=gc();}
    return x*f;
}
inl void write(int x){
    if(x<0){pc('-');x=-x;}
    if(x>9)write(x/10);
    pc(x%10+'0');
}
inl void writei(int x){write(x);pc(' ');}
inl void writel(int x){write(x);pc('\n');}
int n,m,a[N],b[N];
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    n=read();
    for(int i=1;i<=n;i++)a[i]=b[i]=read();
    sort(b+1,b+n+1);
    for(int i=1;i<=n;i++)
        cout<<n-(lower_bound(b+1,b+n+1,a[i]+1)-b)+2<<' ';
    return 0;
}

CF551B

翻译少了一个重要条件:b和c不重叠。
考虑枚举选几个b,看剩下能拼几个c,答案取最大值即可。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inl inline
#define endl '\n'
#define int ll
#define gc cin.get
#define pc cout.put
const int N=2e5+5;
const int M=1e7+5;
const int inf=0x3f3f3f3f3f3f3f3f;
const int mod=1e4+7;
inl int read(){
    int x=0,f=1;char c=gc();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc();}
    while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=gc();}
    return x*f;
}
inl void write(int x){
    if(x<0){pc('-');x=-x;}
    if(x>9)write(x/10);
    pc(x%10+'0');
}
inl void writei(int x){write(x);pc(' ');}
inl void writel(int x){write(x);pc('\n');}
int n,m,numa[N],numb[N],numc[N],cnt[N],ans1(inf),ans2(inf);
char a[N],b[N],c[N];
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    cin>>a+1>>b+1>>c+1;
    int lena=strlen(a+1),lenb=strlen(b+1),lenc=strlen(c+1);
    for(int i=1;i<=lena;i++)numa[a[i]-'a'+1]++;
    for(int i=1;i<=lenb;i++)numb[b[i]-'a'+1]++;
    for(int i=1;i<=lenc;i++)numc[c[i]-'a'+1]++;
    for(int i=1;i<=26;i++)
        if(numb[i])ans1=min(ans1,numa[i]/numb[i]);
    for(int i=1;i<=26;i++)
        if(numc[i])ans2=min(ans2,numa[i]/numc[i]);
    if(ans1>ans2){
        int res1=0,res2=0;
        for(int i=0;i<=ans1;i++){
            int now(inf);
            for(int j=1;j<=26;j++)cnt[j]=numa[j];
            for(int j=1;j<=26;j++)cnt[j]-=i*numb[j];
            for(int j=1;j<=26;j++)
                if(numc[j])now=min(now,cnt[j]/numc[j]);
            if(i+now>res1+res2){
                res1=i,res2=now;
            }
        }
        for(int i=1;i<=res1;i++)cout<<b+1;
        for(int i=1;i<=res2;i++)cout<<c+1;
        for(int i=1;i<=26;i++){
            cnt[i]=numa[i]-res1*numb[i]-res2*numc[i];
            while(cnt[i]--)cout<<(char)('a'+i-1);
        }
    }else{
        int res1=0,res2=0;
        for(int i=0;i<=ans2;i++){
            int now(inf);
            for(int j=1;j<=26;j++)cnt[j]=numa[j];
            for(int j=1;j<=26;j++)cnt[j]-=i*numc[j];
            for(int j=1;j<=26;j++)
                if(numb[j])now=min(now,cnt[j]/numb[j]);
            if(i+now>res1+res2){
                res1=i,res2=now;
            }
        }
        for(int i=1;i<=res1;i++)cout<<c+1;
        for(int i=1;i<=res2;i++)cout<<b+1;
        for(int i=1;i<=26;i++){
            cnt[i]=numa[i]-res1*numc[i]-res2*numb[i];
            while(cnt[i]--)cout<<(char)('a'+i-1);
        }
    }
    return 0;
}

CF551C

答案显然具有单调性,先二分答案。
check时优先把后面的先取完,让往前走的步数最少。
然后判能不能取完即可。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inl inline
#define endl '\n'
#define int ll
#define gc cin.get
#define pc cout.put
const int N=2e5+5;
const int M=1e7+5;
const int inf=0x3f3f3f3f3f3f3f3f;
const int mod=1e4+7;
inl int read(){
    int x=0,f=1;char c=gc();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc();}
    while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=gc();}
    return x*f;
}
inl void write(int x){
    if(x<0){pc('-');x=-x;}
    if(x>9)write(x/10);
    pc(x%10+'0');
}
inl void writei(int x){write(x);pc(' ');}
inl void writel(int x){write(x);pc('\n');}
int n,m,a[N],b[N],sum;
inl bool check(int mid){
    memcpy(b,a,sizeof b);
    int lst=n;if(!lst)return 1;
    for(int i=1;i<=m;i++){
        int x=mid-lst;
        while(b[lst]<=x){
            x-=b[lst--];
            if(!lst)return 1;
        }
        b[lst]-=x;
    }
    return 0;
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    n=read();m=read();
    for(int i=1;i<=n;i++)a[i]=read();
    while(n&&!a[n])n--;
    int l=0,r=1e15,ans;
    while(l<=r){
        int mid=l+r>>1;
        if(check(mid))r=mid-1,ans=mid;
        else l=mid+1;
    }
    cout<<ans<<endl;
    return 0;
}

CF551E

看起来很Ynoi的一道题。
显然2操作没啥好的处理方法,考虑暴力分块。
对于一个块,开unordered_map维护一个值是否出现过。
找到最左/右出现过的块,对这两个块再暴力找即可。
注意map用下标访问会默认往里插入一个空节点,会炸空间。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define inl inline
#define endl '\n'
#define gc cin.get
#define pc cout.put
const int N=5e5+5;
const int M=1e7+5;
const int inf=0x3f3f3f3f;
const int mod=1e4+7;
inl int read(){
    int x=0,f=1;char c=gc();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc();}
    while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48);c=gc();}
    return x*f;
}
inl void write(int x){
    if(x<0){pc('-');x=-x;}
    if(x>9)write(x/10);
    pc(x%10+'0');
}
inl void writei(int x){write(x);pc(' ');}
inl void writel(int x){write(x);pc('\n');}
int n,m,bl[N],len,op,l,r,x,lp[750],rp[750];
ll a[N],tag[750];
unordered_map<ll,bool>mp[750];
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    n=read();m=read();len=sqrt(n);
    for(int i=1;i<=n;i++)a[i]=read();
    for(int i=1;i<=n;i++)bl[i]=(i-1)/len+1;
    for(int i=1;i<=bl[n];i++)lp[i]=(i-1)*len+1;
    for(int i=1;i<=bl[n];i++)rp[i]=min(i*len,n);
    for(int i=1;i<=n;i++)mp[bl[i]][a[i]]=1;
    while(m--){
        op=read();
        if(op==1){
            l=read(),r=read(),x=read();
            int lid=bl[l],rid=bl[r];
            if(lid==rid){
                for(int i=lp[lid];i<=rp[lid];i++)mp[lid].erase(a[i]);
                for(int i=l;i<=r;i++)a[i]+=x;
                for(int i=lp[lid];i<=rp[lid];i++)mp[lid][a[i]]=1;
            }else{
                for(int i=lp[lid];i<=rp[lid];i++)mp[lid].erase(a[i]);
                for(int i=lp[rid];i<=rp[rid];i++)mp[rid].erase(a[i]);
                for(int i=l;bl[i]==lid;i++)a[i]+=x;
                for(int i=lp[lid];i<=rp[lid];i++)mp[lid][a[i]]=1;
                for(int i=r;bl[i]==rid;i--)a[i]+=x;
                for(int i=lp[rid];i<=rp[rid];i++)mp[rid][a[i]]=1;
                for(int i=lid+1;i<=rid-1;i++)tag[i]+=x;
            }
        }else{
            x=read();int l=0,r=0,ans1,ans2;
            for(int i=1;i<=bl[n];i++){
                if(mp[i][x-tag[i]]){
                    if(!l)l=i;
                    r=i;
                }else mp[i].erase(x-tag[i]);
            }
            if(!l){cout<<-1<<endl;continue;}
            for(int i=lp[l];i<=rp[l];i++){
                if(a[i]==x-tag[l]){
                    ans1=i;break;
                }
            }
            for(int i=rp[r];i>=lp[r];i--){
                if(a[i]==x-tag[r]){
                    ans2=i;break;
                }
            }
            cout<<ans2-ans1<<endl;
        }
    }
    return 0;
}
posted @ 2023-12-11 12:42  xiang_xiang  阅读(32)  评论(0)    收藏  举报