Splay 求调 orz
查看原帖
Splay 求调 orz
933983
CodeDay楼主2023/10/23 19:30
#include<iostream>
#include<cstdio>
#include<cmath>
using namespace std;

struct splay_tree{
	#define side_of(x) (x == tr[tr[x].fa].ch[1])
	#define INF (int)INFINITY
	struct node{
		int fa, ch[2];//父节点 子节点 
		int val, cnt, siz;//权值 数量 子树大小 
	}tr[(int)1e6+10];
	int rt, idx;//根结点编号 总结点数 
	inline void pushup(int p){tr[p].siz = tr[p].cnt + tr[tr[p].ch[0]].siz + tr[tr[p].ch[1]].siz;}
	//计算子树大小信息 
	inline int new_node(const int &val, const int fa = 0){//新建节点 
		++idx;
		tr[idx].fa = fa;
		tr[idx].cnt = 1;
		tr[idx].val = val;
		return idx;
	}
	inline void rotate(const int &x){//旋转 
		int y = tr[x].fa;
		int z = tr[y].fa;
		bool sx = side_of(x), sy = side_of(y);
		tr[y].ch[sx] = tr[x].ch[sx^1];
		if(tr[x].ch[sx^1]) tr[tr[x].ch[sx^1]].fa = y;
		tr[x].ch[sx^1] = y;
		tr[y].fa = x;
		if(z) tr[z].ch[sy] = x;
		tr[x].fa = z;
		pushup(y), pushup(x);
	}
	inline void splay(int x){
		for(int f = tr[x].fa; f = tr[x].fa, f; rotate(x))
			if(tr[f].fa) rotate(side_of(f) == side_of(x) ? f : x);
		rt = x;
	}
	inline void Insert(const int &val){//插入 
		int p = rt, fa = 0;
		if(!rt) return rt = new_node(val), void();
		while(1)
		{
			if(tr[p].val == val)
			{
				++tr[p].cnt;
				pushup(p), pushup(fa);
				splay(p);
				return;
			}
			fa = p, p = tr[fa].ch[val>tr[fa].val];
			if(!p)
			{
				tr[fa].ch[val>tr[fa].val] = new_node(val, fa);
				pushup(p), pushup(fa);
				splay(idx);
				return;
			}
		}
	}
	inline int rk(const int &val){//求排名 
		int p = rt, ret = 0, fa = 0;
		while(1){
//			printf("p=%d\n", p);
			if(!p) return splay(fa), ret+1;
			if(val < tr[p].val) fa = p, p = tr[p].ch[0];
			else {
				ret += tr[tr[p].ch[0]].siz;
				if(tr[p].val == val) return splay(p), ret + 1;
				fa = p, p = tr[p].ch[1];
			}
		}
	}
	inline int suc(const int &val){//前驱 
//		show();
		rk(val);
		if(tr[rt].val < val) return tr[rt].val;
		int p = tr[rt].ch[0];
		if(!p) return -INF;
		while(tr[p].ch[1]) p = tr[p].ch[1];
		splay(p);
		return tr[p].val;
	}
	inline int nxt(const int &val){//后继 
		rk(val);
//		show();
		if(tr[rt].val > val) return tr[rt].val;
		int p = tr[rt].ch[1];
		if(!p) return INF;
		while(tr[p].ch[0]) p = tr[p].ch[0];
		splay(p);
		return tr[p].val;
	}
	inline void Delete(const int &val){//删除 
		rk(val);
		const int x = tr[rt].ch[0];
		const int y = tr[rt].ch[1];
		if(!x||!y) return rt = (x|y), void();
		rt = x;
		suc(tr[rt].val);
		tr[rt].ch[1] = y;
		pushup(y), pushup(rt);
	}
	inline int kth(int k){//第k大元素 
		int p = rt, fa = 0;
		while(1)
		{
			if(!p) return tr[fa].val;
			if(tr[tr[p].ch[0]].siz < k)
			{
				k -= tr[p].cnt + tr[tr[p].ch[0]].siz;
				if(k <= 0) return splay(p), tr[p].val;
				fa = p, p = tr[p].ch[1];
			}
			else fa = p, p = tr[p].ch[0];
		}
	}
	void print(int p){//辅助调试 以中序遍历顺序打印 
		if(tr[p].ch[0]) print(tr[p].ch[0]);
		printf("id:%d ls:%d rs:%d val:%d siz:%d\n", p, tr[p].ch[0], tr[p].ch[1], tr[p].val, tr[p].siz);
		if(tr[p].ch[1]) print(tr[p].ch[1]);
	}
	void show(){//调试 
		printf("root:%d\n", rt);
		print(rt);
		puts("");
	}
}Splay;

int main(){
	int n;
	scanf("%d", &n);
	int op, x;
	while(n--)
	{
		scanf("%d %d", &op, &x);
		switch(op)
		{
			case 1: Splay.Insert(x);break;
			case 2: Splay.Delete(x);break;
			case 3: printf("%d\n", Splay.rk(x));break;
			case 4: printf("%d\n", Splay.kth(x));break;
			case 5: printf("%d\n", Splay.suc(x));break;
			case 6: printf("%d\n", Splay.nxt(x));break;
		}
	}
	return 0;
}
/*
4
1 10
1 20
1 30
3 21

16
1 5
1 4
1 3
1 2
1 1
1 6
1 7
1 11
1 9
1 10
1 8
1 12
1 13
1 14
1 15
5 11
*/

rt

出现WA&TLE

望各路好心大佬指点迷津

2023/10/23 19:30
加载中...