P1486 [NOI2004] 郁闷的出纳员
P1486 [NOI2004] 郁闷的出纳员
郁闷的到底是出纳员还是我???
[NOI2004] 郁闷的出纳员
题目描述
输入格式
第一行有两个整数
接下来的
I k
新建一个工资档案,初始工资为 。如果某员工的初始工资低于工资下界,他将立刻离开公司。A k
把每位员工的工资加上 。S k
把每位员工的工资扣除 。F k
查询第 多的工资。
在初始时,可以认为公司里一个员工也没有。
输出格式
对于每条 F
命令,你的程序要输出一行,仅包含一个整数,为当前工资第
输出的最后一行包含一个整数,为离开公司的员工的总数。
请注意,初始工资低于工资下界的员工不算做离开公司的员工。
数据规模与约定
对于全部的测试点,保证:
I
命令的条数不超过 ;A
和S
命令的总条数不超过 ;F
命令的条数不超过 ;- 每次工资调整的调整量不超过
; - 新员工的工资不超过
。 , ,输入的所有数字均在 位带符号整形范围内。
solution:
平衡树练手题,我们维护一颗平衡树。
观察到A和S的命令数十分的少,我们对于每次命令S:
直接把减掉k后不符合条件的点删掉
用FHQ-Treap十分好写就是了
然后对于每次A和S,对应剩下的节点dfs一下来更新权值(由于操作次数少,基本不用担心超时)
然后对于每次查询,直接平衡树基本操作,这里不多赘述
但是这里主要说一些细节:
split(rt,mi-tag,a,b)
我们在每次执行S时,val<mi-tag的都要被切掉(之前写成<mi-tag-1)调了好久
还有就是读懂题目:
if(c=='I'&&x>=mi){insert(rt,x);}
如果他刚开始工资就少,那他必然是不干的
还有一个神仙细节是我写的FHQ-Treap貌似不能直接分裂出一个空树,所以当被割完之后的rt只有一个节点且其权值小于mi-tag时,将它重置然后将rt记为0:
if(t[rt].val<mi-tag&&t[rt].siz==1) { t[rt]={0,0,0,0,0}; rt=0; } tag=0;
然后这题基本就做完了
Code:
#include<bits/stdc++.h> #include<ctime> const int N=3e5+5; using namespace std; int n,m,mi,cnt,rt,tag,ans; struct Tree{ int val,pri,siz,ls,rs; }t[N<<2]; int new_(int val=0) { t[++cnt]={val,rand(),1,0,0}; return cnt; } void pushup(int x) { t[x].siz=t[t[x].ls].siz+t[t[x].rs].siz+1; } void split(int x,int k,int &l,int &r) { if(!x){l=r=0;return ;} if(k<=t[x].val)//in ls { r=x; split(t[x].ls,k,l,t[r].ls); pushup(r); } else//in rs { l=x; split(t[x].rs,k,t[l].rs,r); pushup(l); } } int merge(int x,int y) { if(!x||!y)return x+y; if(t[x].pri<t[y].pri) { t[x].rs=merge(t[x].rs,y); pushup(x); return x; } else { t[y].ls=merge(x,t[y].ls); pushup(y); return y; } } int query_kth(int x,int k) { if(k==t[t[x].ls].siz+1)return t[x].val; if(k<=t[t[x].ls].siz)return query_kth(t[x].ls,k); return query_kth(t[x].rs,k-(t[t[x].ls].siz+1)); } void dfs(int x,int k) { if(!x)return ; t[x].val+=k; dfs(t[x].ls,k);dfs(t[x].rs,k); pushup(x); } void upd_val(int &rt,int k)//-=k { if(k<0) { tag+=k; int a=0,b=0;//val+tag<mi :val<mi-tag split(rt,mi-tag,a,b);//a[1,k-1] : b[k,inf] rt=b; ans+=t[a].siz; dfs(rt,tag); pushup(rt); if(t[rt].val<mi-tag&&t[rt].siz==1) { t[rt]={0,0,0,0,0}; rt=0; } tag=0; } else { tag+=k; dfs(rt,tag); pushup(rt); tag=0; } } void insert(int &rt,int k) { int a=0,b=0; split(rt,k,a,b);//a[1,k] : b[k+1,inf] rt=merge(merge(a,new_(k)),b); pushup(rt); } void work() { cin>>n>>mi; char c; int x; for(int i=1;i<=n;i++) { std::cin>>c>>x; if(c=='I'&&x>=mi){insert(rt,x);} if(c=='A'){upd_val(rt,x);} if(c=='S'){upd_val(rt,-x);} if(c=='F') { int k=t[rt].siz-x+1; printf("%d\n", k>0? query_kth(rt,k) : -1); } } printf("%d",cnt-t[rt].siz); } int main() { //freopen("P1486_3.in","r",stdin);//freopen("P1486.out","w",stdout); srand(clock()); work(); return 0; }