自己电脑做网站/关键词排名监控
Description
OIER 公司是一家大型专业化软件公司,有着数以万计的员工。作为一名出纳员,我的任务之一便是统计每位员工的工资。这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资。如果他心情好,就可能把每位员工的工资加上一个相同的量。反之,如果心情不好,就可能把他们的工资扣除一个相同的量。我真不知道除了调工资他还做什么其它事情。
工资的频繁调整很让员工反感,尤其是集体扣除工资的时候,一旦某位员工发现自己的工资已经低于了合同规定的工资下界,他就会立刻气愤地离开公司,并且再也不会回来了。每位员工的工资下界都是统一规定的。每当一个人离开公司,我就要从电脑中把他的工资档案删去,同样,每当公司招聘了一位新员工,我就得为他新建一个工资档案。
老板经常到我这边来询问工资情况,他并不问具体某位员工的工资情况,而是问现在工资第 k 多的员工拿多少工资。每当这时,我就不得不对数万个员工进行一次漫长的排序,然后告诉他答案。
好了,现在你已经对我的工作了解不少了。正如你猜的那样,我想请你编一个工资统计程序。怎么样,不是很困难吧?Input
第一行有两个非负整数 n 和 min 。n 表示下面有多少条命令,min 表示工资下界。
接下来的 n 行,每行表示一条命令。命令可以是以下四种之一:
“下划线( _ )”表示一个空格,I 命令、A 命令、S 命令中的 k 是一个非负整数,F 命令中的 k 是一个正整数。
在初始时,可以认为公司里一个员工也没有。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 2Sample Output
10
20
-1
2Hint
【数据范围】
I 命令的条数不超过 100000
A 命令和 S 命令的总条数不超过 100
F 命令的条数不超过 100000
每次工资调整的调整量不超过 1000
新员工的工资不超过 100000题解 : Splay
对于每个Splay上的点,维护size和val.
对于几种操作的方法:
插入
先判断该点能否被插入。如果能则计数器加一。
插入时可以将m(增加减少量)先更新Splay,每个点-m(tag标记)。或者直接在加入值上+m;
最后输出离开的员工就用总员工减剩余员工。
增加、减少
外部设置计数器m,在m上加减即可。及时删除。
删除操作:
对于一个节点,可能的情况有两种:
1.当前值小于最小值。
该节点及其左子树都会被删除。将该节点右子树置为该节点父亲的儿子,更新父亲。(若该节点为根节点则将右子树置为根节点)。递归删除右子树。
2.当前值大等于最小值。
直接递归删除左子树即可。
- Code
#include<bits/stdc++.h>
using namespace std;const int Maxn=1e5+50;inline int read()
{char ch=getchar();int i=0,f=1;while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=getchar();}return i*f;
}struct node
{node *fa,*lc,*rc;int val,sze,tag;node():fa(NULL),lc(NULL),rc(NULL){}void upt(){sze=(lc?lc->sze:0)+(rc?rc->sze:0)+1;}
}POOL[Maxn],*pool=POOL,*rt;int n,m,M,cnt;
char ch[2];inline node* newnode(int val)
{++pool;pool->sze=1;pool->val=val;return pool;
}inline bool which(node *now)
{return now->fa->lc==now;
}inline void Rotate(node *x)
{node* y=x->fa,*z=y->fa;x->fa=z,y->fa=x;if(y->lc==x){if(z)(z->lc==y?z->lc:z->rc)=x;if(x->rc)x->rc->fa=y,y->lc=x->rc;else y->lc=NULL;x->rc=y;y->upt();x->upt();}else{if(z)(z->lc==y?z->lc:z->rc)=x;if(x->lc)x->lc->fa=y,y->rc=x->lc;else y->rc=NULL;x->lc=y;y->upt();x->upt();}
}inline void Splay(node* x)
{while(x->fa){node *y=x->fa;if(y->fa){if(which(x)^which(y))Rotate(x);else Rotate(y);}Rotate(x);}rt=x;
}inline void pushdown(node *now,int val)
{now->val-=val;now->tag=0;if(now->lc)now->lc->tag+=val;if(now->rc)now->rc->tag+=val;
}inline node* Insert(node* f,node*& now,int val)
{if(!now){now=newnode(val);now->fa=f;return now;}if(now->tag)pushdown(now,now->tag);if(val<=now->val){node* tmp=Insert(now,now->lc,val);now->upt();return tmp;}else {node* tmp=Insert(now,now->rc,val);now->upt();return tmp;}
}inline void Delete(node *now,int val)
{if(now->tag)pushdown(now,now->tag);if(now->val<val){if(now==rt)rt=now->rc;if(now->rc){now->rc->fa=now->fa;if(now->fa)(now->fa->lc==now?now->fa->lc:now->fa->rc)=now->rc;Delete(now->rc,val);now->rc->upt();if(now->fa)now->fa->upt();}else if(now->fa){(now->fa->lc==now?now->fa->lc:now->fa->rc)=NULL;now->fa->upt();}}else{if(now->lc){Delete(now->lc,val);}now->upt();}
}inline int Find(node* now,int k)
{if(now->tag)pushdown(now,now->tag);if((now->lc?now->lc->sze:0)==(k-1))return now->val;else if((now->lc?now->lc->sze:0)>=k)return Find(now->lc,k);else return Find(now->rc,(k-(now->lc?now->lc->sze:0)-1));
}int main()
{rt=NULL;n=read(),M=read();for(int i=1;i<=n;i++){scanf("%s",ch+1);switch(ch[1]){case 'I':{if(rt)rt->tag+=m;m=0;int val=read();if(val>=M){cnt++;if(!rt)rt=newnode(val);else Splay(Insert(rt->fa,rt,val));}break;}case 'S':{int x=read();m+=x;Delete(rt,m+M);break;}case 'A':{int x=read();m-=x;break;}case 'F':{int k=read();if(!rt){puts("-1");break;}k=rt->sze-k+1;if(k>rt->sze||k<=0)puts("-1");else cout<<Find(rt,k)-m<<endl;break;}}}cout<<cnt-(rt?rt->sze:0)<<endl;
}