BZOJ1503 [NOI2004]郁闷的出纳员 splay
原文链接http://www.cnblogs.com/zhouzhendong/p/8086240.html
题目传送门 - BZOJ1503
题意概括
如果某一个员工的工资低于了min,那么,他会立即离开,并且一定不会回来了。
最后还要输出一个整数,表示离开公司的员工的总数。
题解
还是splay裸题。
加一个懒标记就可以了。
注意,如果一个人还没有进入公司就因为工资太少而走了,不计入离开公司的员工数中
代码
#include <cstring> #include <cstdio> #include <algorithm> #include <cstdlib> #include <cmath> using namespace std; const int N=100005; int fa[N],son[N][2],add[N],val[N],size[N],total,root; void spt_clear(){ total=root=0; memset(fa,0,sizeof fa); memset(son,0,sizeof son); memset(add,0,sizeof add); } void pushup(int x){ size[x]=size[son[x][0]]+size[son[x][1]]+1; } void pushson(int x,int v){ add[x]+=v,val[x]+=v; } void pushdown(int x){ for (int i=0;i<2;i++) if (son[x][i]) pushson(son[x][i],add[x]); add[x]=0; } void pushadd(int x){ if (fa[x]) pushadd(fa[x]); pushdown(x); } int wson(int x){ return son[fa[x]][1]==x; } void rotate(int x){ if (!fa[x]) return; int y=fa[x],z=fa[y],L=wson(x),R=L^1; if (z) son[z][wson(y)]=x; fa[x]=z,fa[y]=x,fa[son[x][R]]=y; son[y][L]=son[x][R],son[x][R]=y; pushup(y),pushup(x); } void splay(int x,int rt){ if (!x) return; if (!rt) root=x; pushadd(x); for (int y=fa[x];fa[x];rotate(x),y=fa[x]) if (fa[y]) rotate(wson(x)==wson(y)?y:x); } void insert(int v,int &x,int pre){ pushdown(x); if (x) return insert(v,son[x][v>val[x]],x); fa[x=++total]=pre,val[x]=v,size[x]=1; splay(x,0); } int findkth(int x,int k){ pushdown(x); if (size[son[x][1]]+1==k) return x; if (size[son[x][1]]>=k) return findkth(son[x][1],k); else return findkth(son[x][0],k-size[son[x][1]]-1); } int findpre(int v,int rt){ if (!rt) return 0; pushdown(rt); if (v>val[rt]){ int x=findpre(v,son[rt][1]); return x?x:rt; } return findpre(v,son[rt][0]); } int findpre(int v){ int res=findpre(v,root); splay(res,0); return res; } int n,Min; int main(){ scanf("%d%d",&n,&Min); spt_clear(); int all=0,now=0; for (int i=1;i<=n;i++){ char op[2]; int v; scanf("%s%d",op,&v); if (op[0]=='I'){ if (v<Min) continue; insert(v,root,0); all++; now++; } if (op[0]=='A') pushson(root,v); if (op[0]=='S'){ pushson(root,-v); int wc=findpre(Min); if (!wc) continue; int rt=root; now-=size[son[rt][0]]+1; fa[root=son[rt][1]]=0; son[rt][1]=0; } if (op[0]=='F') printf("%d\n",v>now?-1:val[findkth(root,v)]); } printf("%d",all-now); return 0; }