花了一天时间调试终于过了。网上非指针的splay太少了,学长大佬们拒绝指导,只能靠自己了。

其实splay是为了保证时间复杂度,所以每次操作进行一次splay。

splay共三种操作:zig,zig_zig,zig_zag。

设当前点为x,y=fa[x],z=fa[y]

1.zig

y为root时直接rotate(x)

2.zig_zig

当x,y,z构成一条链时,先rotate(y),再rotate(x)

3.zig_zag

当非前两种情况时,做两次rotate(x)

void splay(int x)
{
	for(int fa;(fa=tr[x].f);rotate(x))
		if(tr[fa].f)
			rotate((get(fa)==get(x))?fa:x);
	root=x;
}

 模板题

ac代码:

#include<bits/stdc++.h>
#define maxn 100005
#define ls tr[x].ch[0]
#define rs tr[x].ch[1]
using namespace std;
struct node{
	int ch[2],f,key,cnt,size;
}tr[maxn];
int sz,root,n;
void clear(int x)
{
	tr[x].ch[1]=tr[x].ch[0]=tr[x].cnt=tr[x].f=tr[x].key=tr[x].size=0;
}
int get(int x)
{
	return tr[tr[x].f].ch[1]==x;
}
void update(int x)
{
	if(x)
	{
		tr[x].size=tr[x].cnt;
		if(ls)tr[x].size+=tr[ls].size;
		if(rs)tr[x].size+=tr[rs].size;		
	}
}
void rotate(int x)
{
	int y=tr[x].f,z=tr[y].f,whi=get(x);
	tr[y].ch[whi]=tr[x].ch[whi^1];tr[tr[y].ch[whi]].f=y;
	tr[x].ch[whi^1]=y;
	tr[x].f=z;
	if(z)tr[z].ch[get(y)]=x;
	tr[y].f=x;
	update(y);update(x);
}
void splay(int x)
{
	for(int fa;(fa=tr[x].f);rotate(x))
		if(tr[fa].f)
			rotate((get(fa)==get(x))?fa:x);
	root=x;
}
void insert(int x)
{
	if(root==0){root=++sz;tr[sz].key=x;tr[sz].cnt=tr[sz].size=1;return;}
	int now=root;
	while(1)
	{
		if(tr[now].key==x){tr[now].cnt++;tr[now].size++;splay(now);return;}
		int fa=now;
		now=tr[now].ch[tr[now].key<x];
		if(now==0)
		{
			tr[++sz].f=fa;
			tr[sz].cnt=tr[sz].size=1;
			tr[sz].key=x;
			tr[fa].ch[tr[fa].key<x]=sz;
			update(fa);
			splay(sz);
			return;
		}
	}
}
int find_pm(int x)
{
	int now=root,ans=0;
	while(1)
	{
		if(tr[now].key<=x)
		{
			ans+=(tr[now].ch[0]?tr[tr[now].ch[0]].size:0);
			if(tr[now].key==x){splay(now);return ans+1;}
			ans+=tr[now].cnt;
			now=tr[now].ch[1];
		}
		else now=tr[now].ch[0];
	}
}
int find_wz(int x)
{
	int now=root;
	while(1)
	{
		int lsz=tr[tr[now].ch[0]].size;
		if(lsz>=x)now=tr[now].ch[0];
		else if(lsz+tr[now].cnt>=x)return tr[now].key;
		else {
			x-=lsz+tr[now].cnt;
			now=tr[now].ch[1];
		}
	}
}
int pre()
{
	int now=tr[root].ch[0],x=tr[root].key;
	while(tr[now].ch[1]!=0)
	{
		now=tr[now].ch[1];
	}
	return now;
}
int nex()
{
	int now=tr[root].ch[1],x=tr[root].key;
	while(tr[now].ch[0]!=0)
	{
		now=tr[now].ch[0];
	}
	return now;
}
void del(int x)
{
	int w=find_pm(x);
	if(tr[root].cnt>1){tr[root].cnt--;tr[root].size--;return;}
	if(tr[root].ch[0]==0&&tr[root].ch[1]==0){clear(root);root=0;return;}
	if(tr[root].ch[0]==0)
	{
		int newroot=tr[root].ch[1];
		clear(root);
		root=newroot;
		tr[root].f=0;
		return;
	}
	else if(tr[root].ch[1]==0) 
	{
		int newroot=tr[root].ch[0];
		clear(root);
		root=newroot;
		tr[root].f=0;
		return;
	}
	else 
	{
		int nowroot=pre(),oldroot=root;
		splay(nowroot);
		tr[nowroot].ch[1]=tr[oldroot].ch[1];
		tr[tr[oldroot].ch[1]].f=nowroot;
		root=nowroot;
		tr[root].f=0;
		clear(oldroot);
		update(root);
	}
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		int temp,x;
		scanf("%d%d",&temp,&x);
		if(temp==1)insert(x);
		if(temp==2)del(x);
		if(temp==3)printf("%d\n",find_pm(x));
		if(temp==4)printf("%d\n",find_wz(x));
		if(temp==5)insert(x),printf("%d\n",tr[pre()].key),del(x);
		if(temp==6)insert(x),printf("%d\n",tr[nex()].key),del(x);
	}
	return 0;
}

  

posted on 2018-03-09 10:12  geniuschenjj  阅读(203)  评论(1编辑  收藏  举报