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
I 60
I 70
S 50
F 2
I 30
S 15
A 5
F 1
F 2
Sample Output
10
20
-1
2
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 }