首页 > 代码库 > HNOI2004 郁闷的出纳员(Splay)
HNOI2004 郁闷的出纳员(Splay)
郁闷的出纳员
OIER公司是一家大型专业化软件公司,有着数以万计的员工。作为一名出纳员,我的任务之一便是统计每位员工的工资。这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资。如果他心情好,就可能把每位员工的工资加上一个相同的量。反之,如果心情不好,就可能把他们的工资扣除一个相同的量。我真不知道除了调工资他还做什么其它事情。工资的频繁调整很让员工反感,尤其是集体扣除工资的时候,一旦某位员工发现自己的工资已经低于了合同规定的工资下界,他就会立刻气愤地离开公司,并且再也不会回来了。每位员工的工资下界都是统一规定的。每当一个人离开公司,我就要从电脑中把他的工资档案删去,同样,每当公司招聘了一位新员工,我就得为他新建一个工资档案。老板经常到我这边来询问工资情况,他并不问具体某位员工的工资情况,而是问现在工资第k多的员工拿多少工资。每当这时,我就不得不对数万个员工进行一次漫长的排序,然后告诉他答案。好了,现在你已经对我的工作了解不少了。正如你猜的那样,我想请你编一个工资统计程序。怎么样,不是很困难吧?
Input Output输出文件的行数为F命令的条数加一。对于每条F命令,你的程序要输出一行,仅包含一个整数,为当前工资第k多的员工所拿的工资数,如果k大于目前员工的数目,则输出-1。输出文件的最后一行包含一个整数,为离开公司的员工的总数。
Sample Input9 10 I 60 I 70 S 50 F 2 I 30 S 15 A 5 F 1 F 2Sample Output
10 20 -1 2Hint
I命令的条数不超过100000 A命令和S命令的总条数不超过100 F命令的条数不超过100000 每次工资调整的调整量不超过1000 新员工的工资不超过100000
第一次写平衡树,在网上拷了一份板子,但是只懂了一部分,里面的求前驱后继的代码是我在别的代码里粘贴进去的,有待测试。
#include <iostream> #include <cstring> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <time.h> #include <string> #include <map> #include <stack> #include <vector> #include <set> #include <queue> #define maxn 102 const int MAXN=2e5+100; int lim; struct SplayTree { int sz[MAXN]; int ch[MAXN][2]; int pre[MAXN]; int rt,top; inline void up(int x) { sz[x] = cnt[x] + sz[ ch[x][0] ] + sz[ ch[x][1] ]; } inline void Rotate(int x,int f) { int y=pre[x]; ch[y][!f] = ch[x][f]; pre[ ch[x][f] ] = y; pre[x] = pre[y]; if(pre[x]) ch[ pre[y] ][ ch[pre[y]][1] == y ] =x; ch[x][f] = y; pre[y] = x; up(y); } inline void Splay(int x,int goal) { //将x旋转到goal的下面 while(pre[x] != goal) { if(pre[pre[x]] == goal) Rotate(x, ch[pre[x]][0] == x); else { int y=pre[x],z=pre[y]; int f = (ch[z][0]==y); if(ch[y][f] == x) Rotate(x,!f),Rotate(x,f); else Rotate(y,f),Rotate(x,f); } } up(x); if(goal==0) rt=x; } inline void RTO(int k,int goal) { //将第k位数旋转到goal的下面 int x=rt; while(sz[ ch[x][0] ] != k-1) { if(k < sz[ ch[x][0] ]+1) x=ch[x][0]; else { k-=(sz[ ch[x][0] ]+1); x = ch[x][1]; } } Splay(x,goal); } inline void vist(int x) { if(x) { printf("结点%2d : 左儿子 %2d 右儿子 %2d %2d sz=%d\n",x,ch[x][0],ch[x][1],val[x],sz[x]); vist(ch[x][0]); vist(ch[x][1]); } } inline void Newnode(int &x,int c) { x=++top; ch[x][0] = ch[x][1] = pre[x] = 0; sz[x]=1; cnt[x]=1; val[x] = c; } inline void init() { sum=ch[0][0]=ch[0][1]=pre[0]=sz[0]=0; rt=top=0; cnt[0]=0; } inline void Insert(int &x,int key,int f) { if(!x) { Newnode(x,key); pre[x]=f; Splay(x,0); return ; } if(key==val[x]) { cnt[x]++; sz[x]++; Splay(x,0); return ; } else if(key<val[x]) { Insert(ch[x][0],key,x); } else { Insert(ch[x][1],key,x); } up(x); } //找前驱 inline int Get_pre(int r) { if(ch[r][0] == 0)return -1;//不存在 r = ch[r][0]; while(ch[r][1])r = ch[r][1]; return r; } //找后继 inline int Get_next(int r) { if(ch[r][1] == 0)return -1; r = ch[r][1]; while(ch[r][0])r = ch[r][0]; return r; } void del(int &x,int f) { if(!x) return ; if(val[x]>=lim) { del(ch[x][0],x); } else { sum+=sz[ch[x][0]]+cnt[x]; x=ch[x][1]; pre[x]=f; if(f==0) rt=x; del(x,f); } if(x) up(x); } inline void update() { del(rt,0); } inline int find_kth(int x,int k) { if(k<sz[ch[x][0]]+1) { return find_kth(ch[x][0],k); } else if(k > sz[ ch[x][0] ] + cnt[x] ) return find_kth(ch[x][1],k-sz[ch[x][0]]-cnt[x]); else { Splay(x,0); return val[x]; } } int cnt[MAXN]; int val[MAXN]; int sum; } spt; int main() { int n; int m; char op[5]; scanf("%d%d",&n,&m); int w=0; spt.init(); while(n--) { int k; scanf("%s%d",op,&k); if(op[0]==‘I‘) { if(k<m) { continue; } spt.Insert(spt.rt,k-w,0); } else if(op[0]==‘A‘) { w+=k; } else if(op[0]==‘S‘) { w-=k; lim=m-w; spt.update(); } else { int sz=spt.sz[spt.rt]; if(k>sz)printf("-1\n"); else { printf("%d\n",spt.find_kth(spt.rt,sz-k+1)+w); } } } printf("%d\n",spt.sum); return 0; }
HNOI2004 郁闷的出纳员(Splay)