BZOJ 1503: [NOI2004]郁闷的出纳员
1503: [NOI2004]郁闷的出纳员
Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 10527 Solved: 3686
[Submit][Status][Discuss]
Description
OIER公司是一家大型专业化软件公司,有着数以万计的员工。作为一名出纳员,我的任务之一便是统计每位员工的工资。这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资。如果他心情好,就可能把每位员工的工资加上一个相同的量。反之,如果心情不好,就可能把他们的工资扣除一个相同的量。我真不知道除了调工资他还做什么其它事情。工资的频繁调整很让员工反感,尤其是集体扣除工资的时候,一旦某位员工发现自己的工资已经低于了合同规定的工资下界,他就会立刻气愤地离开公司,并且再也不会回来了。每位员工的工资下界都是统一规定的。每当一个人离开公司,我就要从电脑中把他的工资档案删去,同样,每当公司招聘了一位新员工,我就得为他新建一个工资档案。老板经常到我这边来询问工资情况,他并不问具体某位员工的工资情况,而是问现在工资第k多的员工拿多少工资。每当这时,我就不得不对数万个员工进行一次漫长的排序,然后告诉他答案。好了,现在你已经对我的工作了解不少了。正如你猜的那样,我想请你编一个工资统计程序。怎么样,不是很困难吧?
Input
Output
输出文件的行数为F命令的条数加一。对于每条F命令,你的程序要输出一行,仅包含一个整数,为当前工资第k多的员工所拿的工资数,如果k大于目前员工的数目,则输出-1。输出文件的最后一行包含一个整数,为离开公司的员工的总数。
Sample Input
I 60
I 70
S 50
F 2
I 30
S 15
A 5
F 1
F 2
Sample Output
20
-1
2
HINT
I命令的条数不超过100000 A命令和S命令的总条数不超过100 F命令的条数不超过100000 每次工资调整的调整量不超过1000 新员工的工资不超过100000
Source
分析:
裸的Splay,对于+k-k的操作想法和NOIP2016D2T2思路相同,插入一个数的时候先减去flo再插入,这样拎出来的时候直接加上flo就好了...
需要注意的是查询第k大的时候要判一下Splay中还是否存在数字...
代码:
1 #include<algorithm> 2 #include<iostream> 3 #include<cstring> 4 #include<cstdio> 5 //by NeighThorn 6 using namespace std; 7 8 const int maxn=100000+5; 9 10 int n,Min,flo,ans; 11 int root,tot,w[maxn],ls[maxn],rs[maxn],fa[maxn],cnt[maxn],siz[maxn]; 12 13 char opt[3]; 14 15 inline void zig(int x){ 16 int y=fa[x],tmp=siz[y]; 17 if(rs[x]) 18 ls[y]=rs[x],fa[rs[x]]=y,siz[y]=siz[y]-siz[x]+siz[rs[x]],siz[x]=tmp; 19 else 20 ls[y]=0,siz[y]=siz[y]-siz[x],siz[x]=tmp; 21 fa[x]=fa[y]; 22 if(fa[x]){ 23 if(ls[fa[x]]==y) 24 ls[fa[x]]=x; 25 else 26 rs[fa[x]]=x; 27 } 28 fa[y]=x,rs[x]=y; 29 } 30 31 inline void zag(int x){ 32 int y=fa[x],tmp=siz[y]; 33 if(ls[x]) 34 rs[y]=ls[x],fa[ls[x]]=y,siz[y]=siz[y]-siz[x]+siz[ls[x]],siz[x]=tmp; 35 else 36 rs[y]=0,siz[y]=siz[y]-siz[x],siz[x]=tmp; 37 fa[x]=fa[y]; 38 if(fa[x]){ 39 if(ls[fa[x]]==y) 40 ls[fa[x]]=x; 41 else 42 rs[fa[x]]=x; 43 } 44 fa[y]=x,ls[x]=y; 45 } 46 47 inline void splay(int x,int z){ 48 while(fa[x]!=z){ 49 int y=fa[x]; 50 if(fa[y]==z){ 51 if(ls[y]==x) 52 zig(x); 53 else 54 zag(x); 55 } 56 else{ 57 if(ls[fa[y]]==y){ 58 if(ls[y]==x) 59 zig(y),zig(x); 60 else 61 zag(x),zig(x); 62 } 63 else{ 64 if(rs[y]==x) 65 zag(y),zag(x); 66 else 67 zig(x),zag(x); 68 } 69 } 70 } 71 if(!z) 72 root=x; 73 } 74 75 inline void ins(int rt,int x){ 76 if(!rt) 77 w[++tot]=x,siz[tot]=cnt[tot]=1,root=tot; 78 else if(w[rt]==x) 79 cnt[rt]++,siz[rt]++,splay(rt,0); 80 else if(x<w[rt]){ 81 if(!ls[rt]) 82 w[++tot]=x,siz[tot]=cnt[tot]=1,siz[rt]++,fa[tot]=rt,ls[rt]=tot,splay(tot,0); 83 else 84 siz[rt]++,ins(ls[rt],x); 85 } 86 else{ 87 if(!rs[rt]) 88 w[++tot]=x,siz[tot]=cnt[tot]=1,siz[rt]++,fa[tot]=rt,rs[rt]=tot,splay(tot,0); 89 else 90 siz[rt]++,ins(rs[rt],x); 91 } 92 } 93 94 inline void del(int rt,int x){ 95 if(w[rt]==x){ 96 splay(rt,0); 97 if(cnt[rt]>1) 98 cnt[rt]--,siz[rt]--; 99 else{ 100 int l=ls[rt],r=rs[rt]; 101 if(!l) 102 ls[rt]=rs[rt]=fa[rt]=cnt[rt]=siz[rt]=0,fa[r]=0,root=r; 103 else{ 104 while(rs[l]) 105 l=rs[l]; 106 splay(l,rt);ls[rt]=rs[rt]=fa[rt]=cnt[rt]=siz[rt]=0;fa[r]=l,rs[l]=r,siz[l]+=siz[r];root=l,fa[l]=0; 107 } 108 } 109 } 110 else if(x<w[rt]) 111 del(ls[rt],x); 112 else 113 del(rs[rt],x); 114 } 115 116 inline int query(int rt,int x){ 117 if(!ls[rt]){ 118 if(cnt[rt]>=x){ 119 splay(rt,0); 120 return w[rt]; 121 } 122 else 123 return query(rs[rt],x-cnt[rt]); 124 } 125 else{ 126 if(siz[ls[rt]]>=x) 127 return query(ls[rt],x); 128 else if(siz[ls[rt]]+cnt[rt]>=x){ 129 splay(rt,0); 130 return w[rt]; 131 } 132 else 133 return query(rs[rt],x-cnt[rt]-siz[ls[rt]]); 134 } 135 } 136 137 signed main(void){ 138 // freopen("1503.in","r",stdin); 139 // freopen("1503.out","w",stdout); 140 memset(ls,0,sizeof(ls)); 141 memset(rs,0,sizeof(rs)); 142 memset(fa,0,sizeof(fa)); 143 memset(cnt,0,sizeof(cnt)); 144 memset(siz,0,sizeof(siz)); 145 scanf("%d%d",&n,&Min);root=tot=ans=flo=0; 146 for(int i=1,x;i<=n;i++){ 147 scanf("%s%d",opt,&x); 148 if(opt[0]=='I'){ 149 if(x>=Min) 150 ins(root,x-flo); 151 } 152 else if(opt[0]=='A') 153 flo+=x; 154 else if(opt[0]=='S'){ 155 flo-=x; 156 int s=query(root,1); 157 while(s+flo<Min){ 158 del(root,s),ans++; 159 if(siz[root]==0) 160 break; 161 s=query(root,1); 162 } 163 } 164 else{ 165 if(siz[root]<x) 166 puts("-1"); 167 else{ 168 int s=query(root,1); 169 while(s+flo<Min){ 170 del(root,s),ans++; 171 if(siz[root]==0) 172 break; 173 s=query(root,1); 174 } 175 if(siz[root]<x) 176 puts("-1"); 177 else 178 printf("%d\n",query(root,siz[root]-x+1)+flo); 179 } 180 } 181 }printf("%d\n",ans); 182 return 0; 183 }
by NeighThorn