用delta记录对工资的加减,那么添加节点时点权应-delta,输出时+delta
几种操作中减少工资较麻烦:
1.delta-=val;
2.删点
求前驱转到根,删除左子树
这里的删除不用一个一个暴力删,直接断掉子树关系即可
至于求k大 我比较懒直接改成求size-k+1小 (逃)
#include<cstdio> #include<iostream> #include<cstring> using namespace std; const int N=1e5+5; int n,fa[N],cnt[N],son[N][3],size[N],key[N],type,root; int line,ans,num,delta; void clear(int x) { fa[x]=cnt[x]=son[x][1]=son[x][0]=size[x]=key[x]=0; } bool judge(int x) { return son[fa[x]][1]==x; } void up(int x) { if(x) { size[x]=cnt[x]; if(son[x][0])size[x]+=size[son[x][0]]; if(son[x][1])size[x]+=size[son[x][1]]; } } void rotate(int x) { int old=fa[x],oldf=fa[old],lr=judge(x); son[old][lr]=son[x][lr^1]; fa[son[old][lr]]=old; son[x][lr^1]=old; fa[old]=x; fa[x]=oldf; if(oldf)son[oldf][son[oldf][1]==old]=x; up(old);up(x); } void splay(int x) { for(int f;f=fa[x];rotate(x)) if(fa[f])rotate(judge(x)==judge(f)?f:x); root=x; } void ins(int x) { if(!root) { type++; key[type]=x; root=type; cnt[type]=size[type]=1; fa[type]=son[type][0]=son[type][1]=0; return ; } int now=root,f=0; while(1) { if(x==key[now]) { cnt[now]++; up(now); up(f); splay(now); return ; } f=now;now=son[now][key[now]<x]; if(!now) { type++; size[type]=cnt[type]=1; son[type][0]=son[type][1]=0; son[f][x>key[f]]=type; fa[type]=f; key[type]=x; up(f);splay(type); return ; } } } int getnum(int x) { int now=root; while(1) { if(son[now][0]&&x<=size[son[now][0]])now=son[now][0]; else { int tmp=size[son[now][0]]+cnt[now]; if(x<=tmp) return key[now]; x-=tmp;now=son[now][1]; } } } int pre() { if(cnt[root]>1)return root; int now=son[root][0]; while(son[now][1])now=son[now][1]; return now; } void del(int x) { //changeroot(x); if(cnt[root]>1) { cnt[root]--; up(root); return ; } if(!son[root][0]&&!son[root][1]) { clear(root); root=0; return ; } if(!son[root][0]) { int old=root; root=son[root][1]; fa[root]=0; clear(old); return ; } else if(!son[root][1]) { int old=root; root=son[root][0]; fa[root]=0; clear(old); return ; } int old=root,L=pre(); splay(L); son[root][1]=son[old][1]; fa[son[old][1]]=root; clear(old); up(root); } void del_tree() { fa[son[root][0]]=0; size[root]-=size[son[root][0]]; son[root][0]=0; } inline int read() { int x=0,f=1;char ch=getchar(); while(ch<‘0‘||ch>‘9‘) {if(ch==‘-‘)f=-1;ch=getchar();} while(ch>=‘0‘&&ch<=‘9‘) {x=(x<<1)+(x<<3)+ch-‘0‘;ch=getchar();} return x*f; } int main() { n=read();line=read(); char op[3];int val; for(int i=1;i<=n;i++) { scanf("%s",op);val=read(); switch(op[0]) { case ‘I‘: if(val<line)break; else { ins(val-delta); break; } case ‘A‘: delta+=val;break; case ‘S‘: delta-=val; ins(line-delta); ans+=son[root][0]?size[son[root][0]]:0; del_tree(); del(val-delta); break; case ‘F‘: if(size[root]<val)puts("-1"); else printf("%d\n",getnum(size[root]-val+1)+delta); break; } } cout<<ans<<endl; return 0; }
原文:https://www.cnblogs.com/Rorschach-XR/p/11015682.html