求助splay挂了,有详细信息有数据求调
查看原帖
求助splay挂了,有详细信息有数据求调
195331
Mine_KingCattleya楼主2022/5/21 21:56

Rt。调了一下发现大概是查询 xx 的排名的函数挂掉了,有 hack 数据如下:

7
1 5
1 3
1 1
1 2
1 4
2 3
2 1

原本在第一个删除操作查询 33 的排名把 33 旋到树根后树的形态应该是这样:

    3
   / \
  2   4
 /     \
1       5

但是实际上 33 的某一棵子树却消失了,也就是只能查询到左儿子或右儿子。

我怀疑大概是查询排名的函数的问题,但也有可能是其他地方的问题。求大佬帮忙康康/kel

//Think twice,code once.
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int n;
struct Splay
{
	int tot,root;
	int size[100005];
	int son[100005][2];
	int fa[100005];
	int cnt[100005],val[100005];
	int get(int x){return x==son[fa[x]][1];}
	void update(int x){size[x]=size[son[x][0]]+size[son[x][1]]+cnt[x];return ;}
	void clear(int x){size[x]=son[x][0]=son[x][1]=fa[x]=cnt[x]=val[x]=0;return ;}
	void rotate(int x)
	{
		int y=fa[x],z=fa[fa[x]],chk=get(x);
		son[y][chk]=son[x][chk^1];
		if(son[x][chk^1]) fa[son[x][chk^1]]=y;
		son[x][chk^1]=y;fa[y]=x;
		fa[x]=z;
		if(z) son[z][get(y)]=x;
		update(y);
		update(x);
		return ;
	}
	void splay(int x)
	{
		for(int f=fa[x];f=fa[x],f;rotate(x))
			if(fa[f]) rotate(get(x)==get(f)?f:x);
		root=x;
		return ;
	}
	void insert(int k)
	{
		if(!root)
		{
			son[tot][0]=son[tot][1]=fa[tot]=0;
			root=++tot;
			val[tot]=k;
			size[tot]=cnt[tot]=1;
			return ;
		}
		int x=root;
		while(1)
		{
			if(val[x]==k)
			{
				cnt[x]++;
				update(x);
				update(fa[x]);
				splay(x);
				break;
			}
			int lst=x;
			x=son[x][k>val[x]];
			if(!x)
			{
				tot++;
				son[tot][0]=son[tot][1]=0;
				fa[tot]=lst;
				son[lst][k>val[lst]]=tot;
				val[tot]=k;
				size[tot]=cnt[tot]=1;
				update(fa[tot]);
				splay(tot);
				break;
			}
		}
		return ;
	}
	int rank(int x)
	{
		int now=root,num=0;
		while(1)
		{
			if(x<val[now]) now=son[now][0];
			else
			{
				num+=size[son[now][0]];
				if(x==val[now]) break;
				num+=cnt[now];
				now=son[now][1];
			}
		}
		splay(now);
		return num+1;
	}
	int pre(int x)
	{
		int now=root,ans=-1e9;
		while(now)
		{
			if(x>val[now]) ans=max(ans,val[now]);
			now=son[now][x>val[now]];
		}
		return ans;
	}
	int suf(int x)
	{
		int now=root,ans=1e9;
		while(now)
		{
			if(x<val[now]) ans=min(ans,val[now]);
			now=son[now][x>=val[now]];
		}
		return ans;
	}
	int kth(int k)
	{
		int now=root,num=0;
		while(num<k)
			if(num+size[son[now][0]]+cnt[now]<k) now=son[now][1],num+=son[now][0]+cnt[now];
			else if(num+size[son[now][0]]<k&&num+size[son[now][0]]+cnt[now]>=k) break;
			else now=son[now][0];
		return val[now];
	}
	void dlt(int x)
	{
		rank(x);
		if(cnt[root]>1){cnt[root]--;update(root);return ;}
		if(!son[root][0]&&!son[root][1])
		{
			clear(root);
			root=0;
			return ;
		}
		if(!son[root][1])
		{
			int lst=root;
			root=son[root][0];
			fa[root]=0;
			clear(lst);
			return ;
		}
		if(!son[root][0])
		{
			int lst=root;
			root=son[root][1];
			fa[root]=0;
			clear(lst);
			return ;
		}
		int lst=root;
		int now=son[root][0];
		fa[now]=0;
		root=now;
		while(son[now][1]) now=son[now][1];
		splay(now);
		son[root][1]=son[lst][1];
		update(root);
		clear(lst);
		return ;
	}
}s;
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		int op,val;
		scanf("%d%d",&op,&val);
		switch(op)
		{
			case 1:s.insert(val);break;
			case 2:s.dlt(val);break;
			case 3:printf("%d\n",s.rank(val));break;
			case 4:printf("%d\n",s.kth(val));break;
			case 5:printf("%d\n",s.pre(val));break;
			case 6:printf("%d\n",s.suf(val));break;
		}
	}
	return 0;
}
2022/5/21 21:56
加载中...