Splay有个操作卡死循环求调
查看原帖
Splay有个操作卡死循环求调
701221
Chr0n1CleC楼主2022/8/20 21:28
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#define N 100009

struct Splay
{
	int rt, tot, cnt[N], val[N], fa[N], ch[N][2], siz[N];
	inline void updata(int x)
	{
		siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + cnt[x];
	}
	inline bool get(int x)
	{
		return x == ch[fa[x]][1];
	}
	inline void rorate(int x)
	{
		int y = fa[x], z = fa[y], f = get(x);
		ch[y][f] = ch[x][!f];
		if (ch[x][!f])
			fa[ch[x][!f]] = y;
		ch[x][!f] = y;
		fa[y] = x;
		fa[x] = z; 
		if (z)
			ch[z][get(y)] = x;
		updata(y), updata(x);
	}
	inline void splay(int x, int root = 0)
	{
		while (fa[x] != root)
		{
			if (get(x) == get(fa[x]))//三点共线 
				rorate(fa[x]);//先旋转父节点 
			rorate(x);//再旋转子节点 
		}
		if (!root)
			rt = x;//如果时旋转到根,那么根就是 x了 
	}
	inline void insert(int x)
	{
		if (!rt)
		{
			rt = ++ tot;
			val[tot] = x;
			siz[tot] = cnt[tot] = 1;//构建新点 
			return;
		}//树都没有 
		int cur = rt, f = 0;
		while (1)
		{
			if (val[cur] == x)
			{
				cnt[cur] ++;
				siz[cur] ++;
				return;
			}//重复 
			f = cur;
			cur = ch[cur][val[cur] < x];
			if (!cur)
			{
				ch[f][val[f] < x] = ++ tot;//构建关系 
				fa[tot] = f;//构建关系 
				val[tot] = x;
				cnt[tot] = siz[tot] = 1;
				splay(tot);//规定操作完都得splay上去
				return;
			}//到了地方了 
		}
	}
	inline int find(int x)
	{
		int cur = rt;
		while (val[cur] != x && ch[cur][val[cur] < x])
			cur = ch[cur][val[cur] < x];//找值(相当于二分查找) 
		splay(cur);//规定的splay操作 
		return cur;
	}
	inline int nxt(int x)
	{
		find(x);//查找并splay到根 
		if (val[rt] > x)
			return rt;
		int cur = ch[rt][1];
		while (ch[cur][0])//一直跳 
			cur = ch[cur][0];
		splay(cur);
		return cur;
	}
	inline int pre(int x)
	{
		find(x);
		if (val[rt] < x)
			return rt;
		int cur = ch[rt][0];
		while (ch[cur][1])
			cur = ch[cur][1];
		splay(cur);
		return cur; 
	}//同理 
	inline int rank(int x)
	{
		find(x);
		return siz[ch[rt][0]] + 1;//查到 
	}//查找x的排名 
	inline void del(int x)
	{
		int Pre = pre(x), Nxt = nxt(x);
		splay(Pre), splay(Nxt, Pre);//旋转到根 + 旋转到下面 
		int cur = ch[rt][0];//因此左节点必须为x 
		if (cnt[cur] > 1)
			cnt[cur] --, siz[cur] --, splay(cur);
		else
			ch[rt][0] = 0, fa[cur] = 0;
		updata(Nxt);
		updata(Pre);
		splay(rand() % tot + 1);//随机找一个点旋转到根保持平衡 
	}
	inline int xrank(int x)
	{
		int cur = rt;
		while (1)
		{
			if (x < siz[cur])
				cur = ch[cur][0];
			else
			{
				x -= siz[ch[cur][0]] + cnt[cur];
				if (x <= 0)
				{
					splay(cur);
					return val[cur];
				}
				cur = ch[cur][1];
			}
		}
	}//查找排名为x的数 
}T;

int main()
{
	srand(time(0));
	int n;
	int opt, x;
	T.insert(-1e9), T.insert(1e9);
	scanf("%d", &n);
	while (n --)
	{
		scanf("%d%d", &opt, &x);
		if (opt == 1)
			T.insert(x);
		if (opt == 2)
			T.del(x);
		if (opt == 3)
			printf("%d\n", T.rank(x));
		if (opt == 4)
			printf("%d\n", T.xrank(x + 1));
		if (opt == 5)
			printf("%d\n", T.val[T.pre(x)]);
		if (opt == 6)
			printf("%d\n", T.val[T.nxt(x)]);
	}
	
	return 0;
}
2022/8/20 21:28
加载中...