求助各位大佬Splay
查看原帖
求助各位大佬Splay
257621
翼德天尊楼主2020/7/5 08:57
  • 望各位大佬帮忙纠错!

  • 注释是蒟蒻自己加的。

  • 评测记录

  • 感谢各位大佬!

#include<bits/stdc++.h>
using namespace std; 
#define gen e[0].ch[1]
#define INF 999999999
int m,n,po;
int read(){
	int w=0;
	char c=getchar();
	while (c>'9'||c<'0') c=getchar();
	while (c>='0'&&c<='9'){
		w=(w<<3)+(w<<1)+(c^48);
		c=getchar();
	}
	return w;
} 
struct node{
	int v,fa,ch[2],sum,rep;
}e[100005];
int rship(int x){//判断左右子树 
	return e[e[x].fa].ch[1]==x;
}
void cont(int son,int fa,int rs){//连接父子节点 
	e[son].fa=fa;
	e[fa].ch[rs]=son;
}
void chan(int x){//更新sum值 
	e[x].sum=e[e[x].ch[0]].sum+e[e[x].ch[1]].sum+e[x].rep;
}
void turn(int x){//旋转 
	int y=e[x].fa,ygen=e[y].fa,yrship=rship(y),xrship=rship(x);
	int B=e[x].ch[xrship^1];
	cont(B,y,xrship);cont(y,x,(xrship^1));cont(x,ygen,yrship);
	chan(y);chan(x);
}
void splay(int x,int dis){//旋转x至dis 
	dis=e[dis].fa;
	while (e[x].fa!=dis){
		int up=e[x].fa;
		if (e[up].fa==dis) turn(x);
		else if (rship(up)==rship(x)){
			turn(up);
			turn(x);
		}else{
			turn(x);
			turn(x);
		}
	}
}
int find(int x){//寻找x在树中的位置 
	int now=gen;
	while (1){
		if (e[now].v==x){
			splay(now,gen);
			return now;
		}
		int next=x<e[now].v?0:1;
		if (!e[now].ch[next]) return 0;
		now=e[now].ch[next];
	}
} 
void addpo(int x,int fa){//加入一个点 
	n++;
	e[n].v=x;
	e[n].fa=fa;
	e[n].sum=e[n].rep=1;
}
int build(int x){//处理加入一个值 
	po++;
	if (n==0){
		gen=1;
		addpo(x,0);
	}else{
		int now=gen;
		while (1){
			e[now].sum++;
			if (x==e[now].v){
				e[now].rep++;
				return now;
			}
			int next=x<e[now].v?0:1;
			if (!e[now].ch[next]){
				addpo(x,now);
				e[now].ch[next]=n;
				return n;
			}
			now=e[now].ch[next];
		}
	}
	return 0;
}
void kill(int x){//摧毁节点 
	e[x].ch[0]=e[x].ch[1]=e[x].fa=e[x].v=e[x].sum=e[x].rep=0;
	if (x==n) n--;
}
void push(int x){ 
	int add=build(x);
	splay(add,gen);
}
void pop(int x){//删除值 
	int deal=find(x);
	if (!deal) return;
	po--;
	if (e[deal].rep>1){
		e[deal].rep--;
		e[deal].sum--;
		return;
	}
	if (!e[deal].ch[0]){
		gen=e[deal].ch[1];
		e[gen].fa=0;
	}else{
		int l=e[deal].ch[0];
		while (e[l].ch[1]) l=e[l].ch[1];
		splay(l,e[deal].ch[0]);
		int r=e[deal].ch[1];
		cont(r,l,1);cont(l,0,1);
		chan(l);
	}
	kill(deal);
}
int arank(int x){//查询一个数的排名 
	int ans=0,now=gen;
	while (1){
		if (e[now].v==x){
			ans+=e[e[now].ch[0]].sum+1;
			splay(now,gen);
			return ans;
		}
		if (now==0) return 0;
		if (x<e[now].v) now=e[now].ch[0];
		else{
			ans=ans+e[e[now].ch[0]].sum+e[now].rep;
			now=e[now].ch[1];
		}
	}
}
int rerank(int x){//查询一个排名的数 
	if (x>po) return -INF;
	int now=gen;
	while (1){
		int cha=e[now].sum-e[e[now].ch[1]].sum;
		if (x>e[e[now].ch[0]].sum&&x<=cha){
			splay(now,gen);
			return e[now].v;
		}
		if (x<cha) now=e[now].ch[0];
		else{
			x=x-cha;
			now=e[now].ch[1];
		}
	}
}
int low(int x){//查询前驱 
	int now=gen,ans=-INF;
	while (now){
		if (e[now].v<x&&e[now].v>ans) ans=e[now].v;
		if (x>e[now].v) now=e[now].ch[1];
		else now=e[now].ch[0];
	}
	return ans;
}
int upp(int x){//查询后驱 
	int now=gen,ans=INF;
	while (now){
		if (e[now].v>x&&e[now].v<ans) ans=e[now].v;
		if (x<e[now].v) now=e[now].ch[0];
		else now=e[now].ch[1];
	}
	return ans;
}
int main(){
	m=read();
	while (m--){
		int opt=read(),x=read();
		if (opt==1) push(x);
		else if (opt==2) pop(x);
		else if (opt==3) printf("%d\n",arank(x));
		else if (opt==4) printf("%d\n",rerank(x));
		else if (opt==5) printf("%d\n",low(x));
		else if (opt==6) printf("%d\n",upp(x));
	}
    return 0;
}
2020/7/5 08:57
加载中...