首页 > 代码库 > BZOJ 1503: [NOI2004]郁闷的出纳员

BZOJ 1503: [NOI2004]郁闷的出纳员

1503: [NOI2004]郁闷的出纳员

Time Limit: 5 Sec  Memory Limit: 64 MB
Submit: 10527  Solved: 3686
[Submit][Status][Discuss]

Description

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

Input

技术分享

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

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

by NeighThorn

BZOJ 1503: [NOI2004]郁闷的出纳员