自己写的splay模板

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

#define N 300010
const int INF=1<<30;
int tree[N][2],pa[N],cnt[N],rev[N],val[N];
int Max(int a,int b){ return  a>b?a:b; }
class splaytree
{	
public:
	int Root;
	static int idx;
	splaytree(){
		if(!idx) init();
		Root=newnode(-INF);pa[Root]=0;
		tree[Root][1]=newnode(INF);pa[tree[Root][1]]=Root;
		update(tree[Root][1]);update(Root);
	}
	void update(int t)
	{
		//add your code;
		cnt[t]=cnt[tree[t][0]]+cnt[tree[t][1]]+1;
	}
	void push(int t)
	{
		//add your code;
		if(t&&rev[t])
		{
			swap(tree[t][0],tree[t][1]); rev[t]=0;
			if(tree[t][0]) rev[tree[t][0]]^=1;
			if(tree[t][1]) rev[tree[t][1]]^=1;
		}
	}
	int newnode(int v){
		cnt[++idx]=1;val[idx]=v;
		pa[idx]=rev[idx]=tree[idx][0]=tree[idx][1]=0;
		return idx;
	}
	void init()
	{
		memset(pa,0,sizeof(pa));
		memset(rev,0,sizeof(rev));
		memset(cnt,0,sizeof(cnt));
		memset(tree,0,sizeof(tree));
	}
	//roate function that support left roate action and right roate action
	void rotate(int t)
	{
		int p=pa[t];
		int c=(tree[pa[t]][0]==t);
		tree[p][!c]=tree[t][c];
		if(tree[t][c]) pa[tree[t][c]]=p;
		tree[t][c]=p; pa[t]=pa[p];
		if(pa[p])tree[pa[p]][tree[pa[p]][1]==p]=t;
		pa[p]=t;update(p);update(t);	
	}
	//the important function that support splay action
	void splay(int x,int &head)
	{
		int p,pp;
		while(pa[x]&&x!=head){
			p=pa[x];
			if(p==head) rotate(x);
			else {
				pp=pa[p];
				if((tree[pp][0]==p)==(tree[p][0]==x))
					rotate(p),rotate(x);
				else rotate(x),rotate(x);
			}
		}
		if(!pa[x]) head=x;
	}
	//find node by a value in the tree that root is "head"
	int find(int v,int head) 
	{
		int root=head;
		while(root)
		{
			if(v==val[root]) return root;
			if(v<val[root]) root=tree[root][0];
			if(v>val[root]) root=tree[root][1];
		}
		return root;
	}
	int findk(int k,int head)
	{
		int t;
		while(head){
			push(head);t=cnt[tree[head][0]];
			if(k==t+1) return head;
			else if(k<t+1) 
				head=tree[head][0];
			else {
				k-=t+1; head=tree[head][1];
			}
		}
		return 0;
	}
	//find a node that value is v and splay to root
	int access(int v,int &head)
	{
		int root=head;
		while(root){
			if(val[root]==v) break;
			if(val[root]>v) 
				root=tree[root][0];
			else 
				root=tree[root][1];
		}
		if(root) splay(root,head); return root;
	}
	//make a node by value v and insert it 
	int insert(int v,int &head)
	{
		int root=head,p=0;
		int node=newnode(v);
		while(root){
			p=root;
			if(v<val[root])  
				root=tree[root][0];
			else 
				root=tree[root][1];
		}
		if(!p) head=node; 
		else {
			pa[node]=p; tree[p][v>=val[p]]=node;
			splay(node,head); 
		}
		return node;
	}
	//insert a node at the rank k position in the splaytree
	int insertk(int k,int v,int &head)
	{
		int nodek,node=newnode(v);
		if(!head){
			head=node;update(head);
		}
		else {
			nodek=findk(k,head); splay(nodek,head); 
			nodek=findk(k+1,head); splay(nodek,tree[head][1]);
			tree[nodek][0]=node; pa[node]=nodek;
			update(node);update(nodek);update(head);
		}
		return node;
	}
	//join two subtree to a biger tree and return the biger tree's root
	int join(int a,int b)
	{
		if(!a) return b; if(!b) return a;
		if(!tree[a][1]){
			tree[a][1]=b; update(a); return pa[b]=a;
		}
		if(!tree[b][0]){
			tree[b][0]=a; update(b); return pa[a]=b;
		}
		int right=a;
		while(tree[right][1]) right=tree[right][1];
		splay(right,a); tree[a][1]=b; update(a);
		return pa[b]=a;
	}
	//find a node that value is v and split it's two childrens to two splay trees
	void split(int &head,int node,int &a,int &b)
	{
		if(node){
			splay(node,head);
			a=tree[head][0];pa[a]=0;
			b=tree[head][1];pa[b]=0;
		}
	}
	//find a node that value is v and remove the node from the tree that root is "head"
	void remove(int node,int &head)
	{
		int l;
		if(node)
		{
			splay(node,head);l=cnt[tree[node][0]];
			splay(findk(l,head),head); splay(findk(l+2,head),tree[head][1]);
			tree[tree[head][1]][0]=0;  update(tree[head][1]); update(head);
		}
	}
};
int splaytree::idx=0;
void debug(int root)
{
	if(!root) return ;
	debug(tree[root][0]); printf("%d(%d) ",val[root],root); debug(tree[root][1]);
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值