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;
}
posted @ 2024-02-27 10:09  wuhupai  阅读(58)  评论(0编辑  收藏  举报