Luogu P3369 【模板】普通平衡树

解法

就是最普通的splay啦,直接放代码QAQ

代码

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<cmath>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long LL;
const int N=1e5+5;

int read()
{
	int x=0,p=1; char ch=getchar();
	while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
	if(ch=='-') p=-1,ch=getchar();
	while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
	return x*p;
}

int ch[N][2],par[N],val[N],cnt[N],siz[N],tot,root;

int chk(int x) { return ch[par[x]][1]==x; }

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

int rotate(int x)
{
	int y=par[x],z=par[y],k=chk(x),w=ch[x][k^1];
	ch[z][chk(y)]=x,par[x]=z;
	ch[y][k]=w,par[w]=y;
	ch[x][k^1]=y,par[y]=x;
	pushup(y),pushup(x);
}

void splay(int x,int goal)
{
	int y,z;
	while(par[x]!=goal)
	{
		y=par[x],z=par[y];
		if(z!=goal)
			chk(x)==chk(y) ? rotate(y):rotate(x);
		rotate(x);
	}
	if(!goal) root=x;
}

void find(int x)
{
	int u=root;
	while(ch[u][x>val[u]] && x!=val[u]) 
		u=ch[u][x>val[u]];
	splay(u,0);
}

void insert(int x)
{
	int u=root,p=0;
	while(u && val[u]!=x) p=u,u=ch[u][x>val[u]];
	if(u) cnt[u]++;
	else 
	{
		u=++tot;
		if(p) ch[p][x>val[p]]=u;
		ch[u][0]=ch[u][1]=0;
		par[u]=p; val[u]=x;
		cnt[u]=siz[u]=1;
	}
	splay(u,0);
}

int kth(int k)
{
	int u=root;
	if(k>siz[u]) return 0;
	for(; ;)
	{
		if(ch[u][0] && k<=siz[ch[u][0]])
			u=ch[u][0];
		else if(k>siz[ch[u][0]]+cnt[u])
			k-=siz[ch[u][0]]+cnt[u],u=ch[u][1];
			 else 
			 	return u;
	}
}
	
int Next(int x,int f)
{
	find(x);
	int u=root;
	if(val[u]>x && f) return u;
	if(val[u]<x && !f) return u;
	u=ch[u][f];
	while(ch[u][f^1]) u=ch[u][f^1];
	return u;
}

void remove(int x)
{
	int last=Next(x,0),next=Next(x,1);
	splay(last,0),splay(next,last);
	int del=ch[next][0];
	if(cnt[del]>1)
		cnt[del]--,splay(del,0);
	else 
		ch[next][0]=0,pushup(next),pushup(root);
}

int main()		
{
	int n,op,x; 
	n=read();
	insert(INF);
	insert(-INF);
	while(n--)
	{
		op=read(),x=read();
		switch (op)
		{
			case 1: insert(x); break ;
			case 2: remove(x); break ;
			case 3: find(x); printf("%d\n",siz[ch[root][0]]); break ;
			case 4: printf("%d\n",val[kth(x+1)]); break ;
			case 5: printf("%d\n",val[Next(x,0)]); break ;
			case 6: printf("%d\n",val[Next(x,1)]); break ;
		}
	}
    return 0;
}
posted @ 2019-06-01 10:51  小蒟蒻lzq  阅读(107)  评论(0编辑  收藏  举报