P9588 (ds思想)
难度2
还是比较巧妙的。
看到这种操作题,思路基本就是考虑用合适的数据结构去求解每一个操作。在遇到一些比较难搞的操作时可以考虑转换。对于一些删除的操作一定要小心,除非很简单,否则大概率是转换
看到操作一,因为这个数据范围想到只用存一个x就可以了
看到操作二,是删除,等等
看到操作三,考虑二分再加加减减
看到操作四,考虑线段树
以下看了题解
再看操作二,其实不用删除,记录当前队列的头尾即可(一个窗口),记录下删除的数 \(tot\) ,操作三就是求第\(tot+x\)个数,比较好维护
#include<bits/stdc++.h>
#define endl "\n"
using namespace std;
long long c,T,n=2e5,op,x,q[200005],sum[200005],l=0,r=0,tot=0;
long long d[800005];
void push_up(long long p){
d[p]=max(d[p<<1],d[p<<1|1]);
}
void update(long long l,long long r,long long p,long long ad,long long s){
if(l==s&&r==s){
d[p]=ad;
return;
}
long long mid=(l+r)>>1;
if(s<=mid) update(l,mid,p<<1,ad,s);
if(s>mid) update(mid+1,r,p<<1|1,ad,s);
push_up(p);
}
long long getmax(long long l,long long r,long long p,long long s,long long t){
if(l>=s&&r<=t){
return d[p];
}
long long mid=(l+r)>>1,ans=0;
if(s<=mid) ans=max(ans,getmax(l,mid,p<<1,s,t));
if(t>mid) ans=max(ans,getmax(mid+1,r,p<<1|1,s,t));
return ans;
}
int main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin>>c>>T;
l=1;
while(T--){
cin>>op;
if(op==1){
cin>>x;
r++;
q[r]=x;
sum[r]=sum[r-1]+x;
update(1,n,1,x,r);
}else if(op==2){
cin>>x;
long long ans=0;
tot+=x;
bool flag=false;
for(long long i=l;i<=r;i++){
if(sum[i]>tot){
l=i;
flag=true;
break;
}
}
if(flag==false) l=r+1;
}else if(op==3){
cin>>x;
//tot+x;
long long gg=lower_bound(sum+1,sum+r+1,tot+x)-sum;
cout<<q[gg]-(sum[gg]-tot-x)<<endl;
}else{
cout<<getmax(1,n,1,l,r)<<endl;
}
//cout<<l<<"-"<<r<<endl;
}
return 0;
}