#Splay#洛谷 1486 [NOI2004]鬱悶的出納員
阿新 • • 發佈:2020-11-03
分析
考慮加減工資直接打標記,查詢第\(k\)多可以用平衡樹,
刪除有點噁心,這裡考慮Splay,將需要刪除的部分的後繼splay到根節點並將左子樹斷邊
程式碼
#include <cstdio> #include <cctype> #define rr register using namespace std; const int inf=0x7fffffff,N=2000011; int n,mn,delta,ans; inline signed iut(){ rr int ans=0,f=1; rr char c=getchar(); while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar(); while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar(); return ans*f; } inline void print(int ans){ if (ans<0) putchar('-'),ans=-ans; if (ans>9) print(ans/10); putchar(ans%10+48); } struct Splay{ int siz[N],cnt[N],son[N][2],fat[N],w[N],root,tot; inline void pup(int x){siz[x]=siz[son[x][0]]+siz[son[x][1]]+cnt[x];} inline bool Is_R(int x){return son[fat[x]][1]==x;} inline void rotate(int x){ rr int Fa=fat[x],FFa=fat[Fa],wh=Is_R(x); son[FFa][Is_R(Fa)]=x,fat[x]=FFa,son[Fa][wh]=son[x][wh^1], fat[son[x][wh^1]]=Fa,son[x][wh^1]=Fa,fat[Fa]=x,pup(Fa),pup(x); } inline void splay(int x,int tar){ for (;fat[x]!=tar;rotate(x)){ rr int Fa=fat[x],FFa=fat[Fa]; if (FFa!=tar) rotate((Is_R(x)^Is_R(Fa))?x:Fa); } if (!tar) root=x; } inline void Insert(int x){ rr int now=root,Fa=0; while (now&&w[now]!=x) Fa=now,now=son[now][x>w[now]]; if (now) ++cnt[now]; else{ now=++tot; if (Fa) son[Fa][x>w[Fa]]=now; son[now][0]=son[now][1]=0,fat[now]=Fa, w[now]=x,cnt[now]=siz[now]=1; } splay(now,0); } inline void Fsplay(int x){ rr int now=root; if (!now) return; while (son[now][x>w[now]]&&x!=w[now]) now=son[now][x>w[now]]; splay(now,0); } inline signed pre(int x){ Fsplay(x); rr int now=root; if (w[now]<x) return now; now=son[now][0]; while (son[now][1]) now=son[now][1]; return now; } inline signed suf(int x){ Fsplay(x); rr int now=root; if (w[now]>x) return now; now=son[now][1]; while (son[now][0]) now=son[now][0]; return now; } inline signed Delete(int x){ rr int L=1,R=suf(x); splay(L,0),splay(R,L); rr int ans=siz[son[R][0]]; son[R][0]=0,pup(R),pup(L); return ans; } inline signed kth(int rk){ rr int now=root; if (siz[now]<rk) return -1; while (1){ rr int lson=son[now][0]; if (siz[lson]+cnt[now]<rk) rk-=siz[lson]+cnt[now],now=son[now][1]; else if (rk<=siz[lson]) now=son[now][0]; else break; } splay(now,0); return w[now]; } inline void BUILD(){Insert(-inf),Insert(inf);} }Tre; signed main(){ n=iut(),mn=iut(),Tre.BUILD(); for (rr int i=1;i<=n;++i){ rr char c=getchar(); while (!isalpha(c)) c=getchar(); switch (c){ case 'I':{ rr int x=iut(); if (x>=mn) Tre.Insert(x-delta); break; } case 'A':{ delta+=iut(); break; } case 'S':{ delta-=iut(); ans+=Tre.Delete(mn-delta-1); break; } case 'F':{ rr int x=iut(),SIZ=Tre.siz[Tre.root]; if (SIZ-2>=x) print(Tre.kth(SIZ-x)+delta); else print(-1); putchar(10); break; } } } return !printf("%d",ans); }