洛谷1486 【NOI2004】郁闷的出纳员(Splay)

版权声明:欢迎转载!请注明出处!qwq https://blog.csdn.net/g21glf/article/details/86569318

传送门

【题目分析】

说是Splay的板题。。。orz谁来拯救常数巨大的我qwq

其实就是平衡树维护查询区间k大,统计比lim小的数个数,至于全体的加减可以直接用一个标记来搞定。

反正按题意弄就行了qwq

【代码~】

#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e5+10;

int n,lim;
int add,lef;
int rt,tot,pre;
int fa[MAXN],ch[MAXN][2],siz[MAXN],val[MAXN],cnt[MAXN];

int Read(){
	int i=0,f=1;
	char c;
	for(c=getchar();(c>'9'||c<'0')&&c!='-';c=getchar());
	if(c=='-')
	  f=-1,c=getchar();
	for(;c>='0'&&c<='9';c=getchar())
	  i=(i<<3)+(i<<1)+c-'0';
	return i*f;
}

void push_up(int root){
	siz[root]=siz[ch[root][0]]+siz[ch[root][1]]+cnt[root];
}

int which(int x,int y){
	return ch[y][1]==x;
}

void rotate(int x){
	int y=fa[x],z=fa[y];
	int l,r;
	if(!which(x,y))
	  l=0;
	else
	  l=1;
	r=l^1;
	if(z){
		if(!which(y,z)){
			ch[z][0]=x;
		}
		else{
			ch[z][1]=x;
		}
	}
	fa[x]=z;
	fa[y]=x;
	fa[ch[x][r]]=y;
	ch[y][l]=ch[x][r];
	ch[x][r]=y;
	push_up(y);
}

void splay(int x,int k){
	int y,z;
	while(fa[x]!=k){
		y=fa[x],z=fa[y];
		if(z!=k){
			if(!which(y,z)^!which(x,y))
			  rotate(x);
			else
			  rotate(y);
		}
		rotate(x);
	}
	if(k==0)
	  rt=x;
	push_up(x);
}

void build_new(int x){
	if(!rt){
		rt=++tot;
		val[tot]=x;
		siz[tot]=1;
		cnt[tot]=1;
		return ;
	}
	int now=rt;
	while(1){
		siz[now]++;
		if(val[now]==x){
			cnt[now]++;
			return ;
		}
		int y=ch[now][x>val[now]];
		if(!y){
			tot++;
			val[tot]=x;
			cnt[tot]=1;
			siz[tot]=1;
			fa[tot]=now;
			ch[now][x>val[now]]=tot;
			now=tot;
			break;
		}
		now=y;
	}
	splay(now,0);
}

void query_pre(int x,int k){
	if(!x)
	  return ;
	if(val[x]<k){
		pre=x;
		query_pre(ch[x][1],k);
	}
	else{
		query_pre(ch[x][0],k);
	}
}

void push_add(int key){
	int x=lim-key;
	pre=-1;
	query_pre(rt,x);
	if(pre==-1)
	  return ;
	splay(pre,0);
	lef+=siz[ch[pre][0]]+cnt[pre];
	rt=ch[pre][1];
	fa[ch[pre][1]]=0;
}

int query_kth(int x,int k){
	if(!x)
	  return -1;
	if(siz[ch[x][1]]>=k)
	  return query_kth(ch[x][1],k);
	if(siz[ch[x][1]]+cnt[x]>=k)
	  return val[x]+add;
	return query_kth(ch[x][0],k-siz[ch[x][1]]-cnt[x]);
}

int main(){
	n=Read(),lim=Read();
	while(n--){
		char cz[5];
		scanf("%s",cz);
		if(cz[0]=='A'){
			int x=Read();
			add+=x;
		}
		if(cz[0]=='S'){
			int x=Read();
			add-=x;
			push_add(add);
		}
		if(cz[0]=='F'){
			int k=Read();
			cout<<query_kth(rt,k)<<'\n';
		}
		if(cz[0]=='I'){
			int x=Read();
			if(x<lim)
			  continue;
			build_new(x-add);
		}
	}
	cout<<lef<<'\n';
	return 0;
}

 

猜你喜欢

转载自blog.csdn.net/g21glf/article/details/86569318