【NOI2004】【洛谷P1486】郁闷的出纳员(Splay写法)

时间:2019-01-23
本文章向大家介绍【NOI2004】【洛谷P1486】郁闷的出纳员(Splay写法),主要包括【NOI2004】【洛谷P1486】郁闷的出纳员(Splay写法)使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

传送门

平衡树简单题

因为是全局加减

维护一下全局一个addadd表示当前工资加减情况

删除就把最低要求的后继SplaySplay到根

然后把左儿子删去就是了

因为个人代码是旋转了后继,为了保证有后继要先插入一个极大值


代码:

#include<bits/stdc++.h>
using namespace std;
inline int read(){
	char ch=getchar();
	int res=0,f=1;
	while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
	while(isdigit(ch))res=(res<<3)+(res<<1)+(ch^48),ch=getchar();
	return res*f;
}
const int N=100006;
char c[5];
int fa[N],son[N][2],rt,tot,n,add,mn,num,ans,siz[N],val[N],cnt[N];
#define lc(u) son[u][0]
#define rc(u) son[u][1]
inline void pushup(int u){
	siz[u]=siz[lc(u)]+siz[rc(u)]+cnt[u];
}
inline void rotate(int v){
	int u=fa[v],z=fa[u];
	int t=(rc(u)==v);
	son[z][rc(z)==u]=v;
	fa[v]=z;
	son[u][t]=son[v][t^1];
	fa[son[v][t^1]]=u;
	fa[u]=v,son[v][t^1]=u;
	pushup(u),pushup(v);
}
inline void splay(int v,int goal){
	while(fa[v]!=goal){
		int u=fa[v],z=fa[u];
		if(z!=goal)
			(lc(z)==u)^(lc(u)==v)?rotate(v):rotate(u);
		rotate(v);
	}
	if(!goal)rt=v;
}
inline void insert(int x){
	int u=rt,f=0;
	while(u&&val[u]!=x){
		f=u,u=son[u][x>val[u]];
	}
	if(u)cnt[u]++;
	else{
		u=++tot;if(f)son[f][x>val[f]]=u;
		fa[u]=f;val[u]=x,siz[u]=cnt[u]=1;
	}
	splay(u,0);
}
inline void find(int x){
	int u=rt;
	if(!u)return;
	while(son[u][x>val[u]]&&val[u]!=x)
		u=son[u][x>val[u]];
	splay(u,0);
}
inline int nxt(int x){
	find(x);
	int u=rt;
	if(val[u]>=x)return u;
	u=rc(u);
	while(lc(u))u=lc(u);
	return u;
}
inline int kth(int k){
	int u=rt;
	if(siz[u]<k||k<=0)return -1;
	while(224){
		int v=lc(u);
		if(siz[v]+cnt[u]<k){
			k-=siz[v]+cnt[u];u=rc(u);
		}
		else{
			if(siz[v]>=k)u=v;
			else return val[u];
		}
	}
}
int main(){
	n=read(),mn=read();insert(199999999);
	for(int i=1;i<=n;i++){
		scanf("%s",c);
		int x=read();
		if(c[0]=='I'){
			if(x>=mn){
				insert(x-add);num+=1;
			}
		}
		else if(c[0]=='A'){
			add+=x;
		}
		else if(c[0]=='S'){
			add-=x;
			int lv=nxt(mn-add);
			splay(lv,0);
			ans+=siz[lc(rt)];
			num-=siz[lc(rt)];
			cnt[lc(rt)]=siz[lc(rt)]=0,lc(rt)=0,siz[0]=0;
			pushup(rt);
		}
		else{
			int p=kth(num-x+1);
			cout<<(p==-1?p:p+add)<<'\n';
		}
		//cout<<num<<'\n';
	}
	cout<<ans<<'\n';
}