洛谷 1486 郁闷的出纳员【Treap】
【题意概述】
要求维护一个序列支持以下操作:
1,插入元素x;
2,把序列的所有元素加上x;
3,把序列的所有元素减去x,同时低于一个给定的下限的元素马上被删除;
4,询问序列中第k大的元素。
【题解】
Treap
用一个delta记录元素的增减情况,即实际上的元素的值应该是qval(root,x)+delta,那么插入元素时插入的应该是Val-delta.
每次加减操作的时候改delta和下限Minwage,加操作的时候Minwage-=val(即下限相对于元素值减小了Val),减操作的时候Minwage+=val(即下限相对于元素值增加了Val)
每次减操作时分裂出序列里小于Minwage的元素,把它们扔掉即可。
1 #include<cstdio> 2 #include<algorithm> 3 #define ls (a[u].l) 4 #define rs (a[u].r) 5 using namespace std; 6 const int maxn=200010; 7 int n,k,x,y,z,v,tot,root,Minwage,Minnow,delta; 8 char c,c2; 9 struct treap{int l,r,v,rnd,size;}a[maxn]; 10 inline int read(){ 11 int k=0,f=1; char c=getchar(); 12 while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); 13 while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar(); 14 return k*f; 15 } 16 void newnode(int val){a[++tot]=(treap){0,0,val,rand()+1,1};} 17 void update(int u){a[u].size=a[ls].size+a[rs].size+1;} 18 void split(int u,int k,int &x,int &y){ 19 if(!k){x=0; y=u; return;} 20 if(a[u].size==k){x=u; y=0; return;} 21 if(a[ls].size>=k) split(ls,k,x,ls),y=u; 22 else split(rs,k-a[ls].size-1,rs,y),x=u; 23 update(u); 24 } 25 int merge(int x,int y){ 26 if(!x||!y) return x+y; 27 if(a[x].rnd<a[y].rnd){a[x].r=merge(a[x].r,y); update(x); return x;} 28 else{a[y].l=merge(x,a[y].l); update(y); return y;} 29 } 30 int qrank(int u,int val){ 31 if(!u) return 0; 32 return a[u].v>=val?qrank(ls,val):qrank(rs,val)+a[ls].size+1; 33 } 34 int qval(int u,int k){ 35 if(a[ls].size+1==k) return a[u].v; 36 return a[ls].size>=k?qval(ls,k):qval(rs,k-a[ls].size-1); 37 } 38 int main(){ 39 srand(20020705); 40 n=read(); Minwage=Minnow=read(); 41 while(n--){ 42 c=getchar(); 43 while(c!='I'&&c!='A'&&c!='S'&&c!='F') c=getchar(); 44 c2=getchar(); v=read(); 45 if(c=='I'&&v>=Minwage){ 46 split(root,qrank(root,v-delta),x,y); 47 newnode(v-delta); root=merge(merge(x,tot),y); 48 } 49 if(c=='A') Minnow-=v,delta+=v; 50 if(c=='S'){ 51 Minnow+=v; delta-=v; 52 split(root,qrank(root,Minnow),x,y); 53 root=y; 54 } 55 if(c=='F') printf("%d\n",a[root].size>=v?qval(root,a[root].size-v+1)+delta:-1); 56 } 57 return printf("%d",tot-a[root].size),0; 58 }