BZOJ[NOI2004]郁闷的出纳员 | Splay板子题
题目:
洛谷也能评测....还有我wa了10多次的记录233
题解:
不要想得太复杂,搞一个全局变量记录一下工资的改变量Delta,这样可以等询问的时候就输出val+Delta,然后插入的时候插入x-Delta
不要想会不会有员工工资一样,直接插入就好,这样省不少代码量.
对于降工资操作,插入一个min-Delta节点,ans+=左子树大小,右儿子作为新的根节点
直接走的员工不要算ans
#include<cstdio> #include<algorithm> #include<cstring> #define N 200010 #define which(x) (ls[fa[(x)]]==x) using namespace std; int sz[N],ls[N],rs[N],val[N],fa[N],n,lim,k,tot,delta,ans,root; char s[N]; void Pushup(int x){sz[x]=1+sz[ls[x]]+sz[rs[x]];} void Rotate(int u) { int v=fa[u],w=fa[v],b=which(u)?rs[u]:ls[u]; if (w) which(v)?ls[w]=u:rs[w]=u; which(u)?(ls[v]=b,rs[u]=v):(rs[v]=b,ls[u]=v); fa[u]=w,fa[v]=u; if (b) fa[b]=v; Pushup(v);Pushup(u); } void Splay(int u) { while (fa[u]) { if (fa[fa[u]]) if (which(u)==which(fa[u])) Rotate(fa[u]); else Rotate(u); Rotate(u); } root=u; } void Insert(int x) { int cur=root,v=0,dir; while (cur) { if (val[v=cur]>=x) cur=ls[cur],dir=0; else cur=rs[cur],dir=1; sz[v]++; } val[++tot]=x,fa[tot]=v,sz[tot]=1; if (v) dir==0?ls[v]=tot:rs[v]=tot; Splay(tot); } int getkth(int k) { int cur=root; while (cur) { if (sz[ls[cur]]>=k) cur=ls[cur]; else if (sz[ls[cur]]+1>=k) return val[cur]; else k-=sz[ls[cur]]+1,cur=rs[cur]; } return val[cur]; } void Delete() { Insert(lim-delta); ans+=sz[ls[root]]; root=rs[root],fa[root]=0; } int main() { scanf("%d%d",&n,&lim); for (int i=1;i<=n;i++) { scanf("%s%d",s+1,&k); if (s[1]=='I') if (k>=lim) Insert(k-delta); if (s[1]=='A') delta+=k; if (s[1]=='S') delta-=k,Delete(); if (s[1]=='F') if (sz[root]<k || root==0) puts("-1"); else printf("%d\n",getkth(sz[root]-k+1)+delta); } printf("%d",ans); return 0; }