洛谷 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 }
View Code

 

posted @ 2017-12-21 21:56  Driver_Lao  阅读(232)  评论(0编辑  收藏  举报