BZOJ1503: [NOI2004]郁闷的出纳员(Splay)

Description

OIER公司是一家大型专业化软件公司,有着数以万计的员工。作为一名出纳员,我的任务之一便是统计每位员工的
工资。这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资。如果他心情好
,就可能把每位员工的工资加上一个相同的量。反之,如果心情不好,就可能把他们的工资扣除一个相同的量。我
真不知道除了调工资他还做什么其它事情。工资的频繁调整很让员工反感,尤其是集体扣除工资的时候,一旦某位
员工发现自己的工资已经低于了合同规定的工资下界,他就会立刻气愤地离开公司,并且再也不会回来了。每位员
工的工资下界都是统一规定的。每当一个人离开公司,我就要从电脑中把他的工资档案删去,同样,每当公司招聘
了一位新员工,我就得为他新建一个工资档案。老板经常到我这边来询问工资情况,他并不问具体某位员工的工资
情况,而是问现在工资第k多的员工拿多少工资。每当这时,我就不得不对数万个员工进行一次漫长的排序,然后
告诉他答案。好了,现在你已经对我的工作了解不少了。正如你猜的那样,我想请你编一个工资统计程序。怎么样
,不是很困难吧?

Input

第一行有两个非负整数n和min。n表示下面有多少条命令,min表示工资下界。
接下来的n行,每行表示一条命令。命令可以是以下四种之一:
名称 格式 作用
I命令 I_k 新建一个工资档案,初始工资为k。
                如果某员工的初始工资低于工资下界,他将立刻离开公司。
A命令 A_k 把每位员工的工资加上k
S命令 S_k 把每位员工的工资扣除k
F命令 F_k 查询第k多的工资
_(下划线)表示一个空格,I命令、A命令、S命令中的k是一个非负整数,F命令中的k是一个正整数。
在初始时,可以认为公司里一个员工也没有。
I命令的条数不超过100000 
A命令和S命令的总条数不超过100 
F命令的条数不超过100000 
每次工资调整的调整量不超过1000 
新员工的工资不超过100000

Output

输出行数为F命令的条数加一。
对于每条F命令,你的程序要输出一行,仅包含一个整数,为当前工资第k多的员工所拿的工资数,
如果k大于目前员工的数目,则输出-1。
输出文件的最后一行包含一个整数,为离开公司的员工的总数。

Sample Input

9 10
I 60
I 70
S 50
F 2
I 30
S 15
A 5
F 1
F 2

Sample Output

10
20
-1
2

解题思路:

splay,维护懒惰标记。

splay支持删除子树,是比treap优秀的关键。

代码:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cstring>
  4 #include<algorithm>
  5 #define lll tr[spc].ch[0]
  6 #define rrr tr[spc].ch[1]
  7 #define ls ch[0]
  8 #define rs ch[1]
  9 #define rrl tr[tr[root].rs].ls
 10 typedef long long lnt;
 11 struct trnt{
 12     int ch[2];
 13     int fa;
 14     lnt lzt;
 15     lnt val;
 16     int wgt;
 17     int num;
 18 }tr[1000000],str;
 19 int sta,fin;
 20 int root;
 21 int n;
 22 lnt m;
 23 int top;
 24 int siz=2;
 25 char cmd[1000];
 26 int bin[1000000];
 27 bool whc(int spc)
 28 {
 29     return tr[tr[spc].fa].rs==spc;
 30 }
 31 int del(int &spc)
 32 {
 33     bin[++top]=spc;
 34     int ans=tr[spc].wgt;
 35     spc=0;
 36     return ans;
 37 }
 38 int newp(void)
 39 {
 40     if(top)
 41     {
 42         int spc=bin[top--];
 43         if(lll)
 44             del(lll);
 45         if(rrr)
 46             del(rrr);
 47         tr[spc]=str;
 48         return spc;
 49     }
 50     return ++siz;
 51 }
 52 void pushup(int spc)
 53 {
 54     tr[spc].wgt=tr[spc].num;
 55     if(lll)
 56         tr[spc].wgt+=tr[lll].wgt;
 57     if(rrr)
 58         tr[spc].wgt+=tr[rrr].wgt;
 59     return ;
 60 }
 61 void add(int spc,lnt v)
 62 {
 63     if(!spc)
 64         return ;
 65     tr[spc].val+=v;
 66     tr[spc].lzt+=v;
 67     return ;
 68 }
 69 void pushdown(int spc)
 70 {
 71     if(!spc)
 72         return ;
 73     if(tr[spc].lzt)
 74     {
 75         add(lll,tr[spc].lzt);
 76         add(rrr,tr[spc].lzt);
 77         tr[spc].lzt=0;
 78     }
 79     return ;
 80 }
 81 void recal(int spc)
 82 {
 83     if(tr[spc].fa)
 84         recal(tr[spc].fa);
 85     pushdown(spc);
 86     return ;
 87 }
 88 void rotate(int spc)
 89 {
 90     int f=tr[spc].fa;
 91     bool k=whc(spc);
 92     tr[f].ch[k]=tr[spc].ch[!k];
 93     tr[spc].ch[!k]=f;
 94     tr[tr[f].fa].ch[whc(f)]=spc;
 95     tr[spc].fa=tr[f].fa;
 96     tr[f].fa=spc;
 97     tr[tr[f].ch[k]].fa=f;
 98     pushup(f);
 99     pushup(spc);
100     return ;
101 }
102 void splay(int spc,int f)
103 {
104     recal(spc);
105     while(tr[spc].fa!=f)
106     {
107         int ft=tr[spc].fa;
108         if(tr[ft].fa==f)
109         {
110             rotate(spc);
111             break;
112         }
113         if(whc(spc)^whc(ft))
114             rotate(spc);
115         else
116             rotate(ft);
117         rotate(spc);
118     }
119     if(!f)
120         root=spc;
121     return ;
122 }
123 int ansp;
124 void kth(int spc,int k)
125 {
126     if(!spc)
127     {
128         ansp=-1;
129         return ;
130     }
131     pushdown(spc);
132     if(tr[rrr].wgt>=k)
133         return kth(rrr,k);
134     if(tr[rrr].wgt+tr[spc].num>=k)
135     {
136         ansp=spc;
137         return ;
138     }
139     return kth(lll,k-tr[spc].num-tr[rrr].wgt);
140 }
141 void maxmin(int spc,lnt v)
142 {
143     if(!spc)
144         return ;
145     pushdown(spc);
146     if(tr[spc].val<v)
147     {
148         ansp=spc;
149         return maxmin(rrr,v);
150     }
151     return maxmin(lll,v);
152 }
153 void minmax(int spc,lnt v)
154 {
155     if(!spc)
156         return ;
157     pushdown(spc);
158     if(tr[spc].val>v)
159     {
160         ansp=spc;
161         return minmax(lll,v);
162     }
163     return minmax(rrr,v);
164 }
165 int main()
166 {
167     
168     scanf("%d%lld",&n,&m);
169     root=1;
170     sta=1;
171     fin=2;
172     tr[1]=(trnt){{0,2},0,0,-0x3f3f3f3f3f3f3f3fll,0,0};
173     tr[2]=(trnt){{0,0},1,0,0x3f3f3f3f3f3f3f3fll,0,0};
174     int ans=0;
175     while(n--)
176     {
177         lnt x;
178         scanf("%s",cmd+1);
179         scanf("%lld",&x);
180         if(cmd[1]=='I')
181         {
182             if(x<m)
183                 continue;
184             maxmin(root,x);
185             splay(ansp,0);
186             minmax(root,x);
187             splay(ansp,root);
188             if(rrl)
189             {
190                 tr[rrl].num++;
191             }else{
192                 rrl=newp();
193                 tr[rrl]=(trnt){{0,0},tr[root].rs,0,x,1,1};
194             }
195             pushup(rrl);
196             pushup(tr[root].rs);
197             pushup(root);
198         }else if(cmd[1]=='A')
199         {
200             if(!x)
201                 continue;
202             splay(sta,0);
203             splay(fin,root);
204             add(rrl,x);
205         }else if(cmd[1]=='S')
206         {
207             splay(sta,0);
208             splay(fin,root);
209             ansp=-1;
210             add(rrl,-x);
211             minmax(rrl,m-1);
212             if(ansp==-1)
213                 continue;
214             splay(sta,0);
215             splay(ansp,root);
216             if(!rrl)
217                 continue;
218             ans+=del(rrl);
219             pushup(tr[root].rs);
220             pushup(root);
221         }else{
222             splay(sta,0);
223             splay(fin,root);
224             kth(rrl,x);
225             if(ansp==-1)
226                 printf("%d\n",-1);
227             else
228                 printf("%lld\n",tr[ansp].val);
229         }
230         splay(sta,0);
231         splay(fin,root);
232         ansp=-1;
233         minmax(rrl,m-1);
234         if(ansp==-1)
235             continue;
236         splay(sta,0);
237         splay(ansp,root);
238         if(!rrl)
239             continue;
240         ans+=del(rrl);
241         pushup(tr[root].rs);
242         pushup(root);
243     }
244     printf("%d\n",ans);
245     return 0;
246 }

 

posted @ 2018-09-29 19:38  Unstoppable728  阅读(195)  评论(0编辑  收藏  举报