【Luogu】P1486郁闷的出纳员(Splay)
名副其实的调了一下午……
每做一道题都是对我那不规范的Splay代码的刀刻斧凿一般的修正啊……
Splay。如果有一批员工不干了,那就找还能干的薪水最少的员工,把它splay到根,删除它的左子树。
然后其他地方加一下标记乱搞就行,这个标记……跟NOIP蚯蚓那个题很像。qwq。
#include<cstdio> #include<cstring> #include<cctype> #include<algorithm> #include<cstdlib> #define maxn 1000200 using namespace std; inline long long read(){ long long num=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)){ num=num*10+ch-'0'; ch=getchar(); } return num*f; } int CNT; long long ans; struct Splay{ struct Node{ int sum,size,fa,e[2],val; }tree[maxn]; int point,tot,root; Splay(){point=tot=root=0; } inline int iden(int x){ return x==tree[tree[x].fa].e[0]?0:1; } inline void connect(int x,int fa,int how){ tree[x].fa=fa; tree[fa].e[how]=x; } inline void update(int x){ tree[x].size=tree[tree[x].e[0]].size+tree[tree[x].e[1]].size+tree[x].sum; } inline void rotate(int x){ int y=tree[x].fa; int r=tree[y].fa; if(root==y) root=x; int sony=iden(x); int sonr=iden(y); int b=tree[x].e[sony^1]; connect(b,y,sony); connect(y,x,sony^1); connect(x,r,sonr); update(y); update(x); } void splay(int pos,int to){ to=tree[to].fa; while(tree[pos].fa!=to){ if(tree[tree[pos].fa].fa==to) rotate(pos); else if(iden(pos)==iden(tree[pos].fa)){ rotate(tree[pos].fa); rotate(pos); } else{ rotate(pos); rotate(pos); } } } int create(int val,int fa){ tree[++tot].val=val; tree[tot].fa=fa; tree[tot].sum=tree[tot].size=1; return tot; } int build(int val){ if(root==0){ root=create(val,0); return root; } int now=root; while(now){ tree[now].size++; if(tree[now].val==val){ tree[now].sum++; return now; } int nxt=val<tree[now].val?0:1; if(tree[now].e[nxt]==0){ connect(create(val,now),now,nxt); update(now); return tot; } now=tree[now].e[nxt]; } return 0; } inline void insert(int val){ int p=build(val); if(++CNT==50){ CNT=0; splay(p,root); } } inline int find(int val){ int now=root; while(now){ if(tree[now].val==val) return now; int nxt=val<tree[now].val?0:1; now=tree[now].e[nxt]; } return 0; } int upper(int val){ int now=root,ans=root; while(now){ if(tree[now].val==val) return now; if(val<tree[now].val){ ans=now; now=tree[now].e[0]; } else now=tree[now].e[1]; } return ans; } void dele(int val){ int deal=upper(val); if(tree[deal].val<val){ ans+=tree[root].size; root=0; return; } splay(deal,root); ans+=tree[tree[deal].e[0]].size; tree[tree[deal].e[0]].fa=0; tree[deal].e[0]=0; update(deal); } int arank(int rnk){ int now=root; while(rnk){ int used=tree[now].size-tree[tree[now].e[1]].size; if(tree[tree[now].e[0]].size<rnk&&used>=rnk) return tree[now].val; if(rnk<=used) now=tree[now].e[0]; else{ rnk-=used; now=tree[now].e[1]; } } if(++CNT==50&&now){ splay(now,root); CNT=0; } return tree[now].val; } int query(int rnk,long long tag){ if(tree[root].size<rnk) return -1; return arank(tree[root].size-rnk+1)+tag; } }s; long long tag=0; int main(){int n=read(),m=read(); for(int i=1;i<=n;++i){ char c[10];int x; scanf("%s%d",c,&x); switch(c[0]){ case 'I': if(x>=m) s.insert(x-tag); break; case 'A': tag+=x; break; case 'S': tag-=x; s.dele(m-tag); break; case 'F': printf("%d\n",s.query(x,tag)); break; } } printf("%lld\n",ans); return 0; }