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;
}

浙公网安备 33010602011771号