各种树模板(splay,线段树,可持久化线段树...)

这是裸的排序Splay

AC tyvj1728 普通平衡树


#include <cstdio>
#include <iostream>
#include <fstream>

#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>

typedef long long int ll;
typedef double db;

using namespace std;

struct SplayTree
{
	struct node
	{
		int v;
		int tot;
		node*s[2];
		node*f;
		
		void update()
		{
			tot=s[0]->tot + s[1]->tot +1;
		}
	};
	node*pool;
	node*nt;
	node*nil;
	node*newnode(node*f,int v)
	{
		nt->v=v;
		nt->tot=1;
		nt->s[0]=nt->s[1]=nil;
		nt->f=f;
		return nt++;
	}
	
	node*root;
	
	SplayTree(int size)
	{
		pool=new node[size+1];
		nt=pool;
		nil=newnode(NULL,-1);
		nil->tot=0;
		nil->f=nil->s[0]=nil->s[1]=nil;
		root=nil;
	}
	
	//===============================================
	
	void update(node*x)
	{
		x->tot= x->s[0]->tot + x->s[1]->tot +1;
	}
	
	void rot(node*x)
	{
		if(x==nil) return ;
		
		node*y=x->f;
		int k=(x==y->s[0]);
		
		y->s[k^1]=x->s[k];
		if(x->s[k]!=nil) x->s[k]->f=y;
		
		x->f=y->f;
		if(y==y->f->s[0]) y->f->s[0]=x;
		else if(y==y->f->s[1]) y->f->s[1]=x;
		
		y->f=x;
		x->s[k]=y;
		
		y->update();
	}
	
	void splay(node*x) { splay(x,nil); }
	void splay(node*x,node*t)
	{
		if(x==nil) return ;
		while(x->f!=t)
		{
			node*y=x->f;
			if(y->f!=t) 
			if((x==y->s[0])^(y==y->f->s[0]))
				rot(y); else rot(x);
			rot(x);
		}
		x->update();
		
		if(t==nil) root=x;
	}
	
	//=============================================
	
	void Insert(int v)
	{
		if(root==nil)
		{
			root=newnode(nil,v);
			return ;
		}
		
		node*x=root;
		node*y=x;
		while(x!=nil)
		{
			y=x;
			if(v<x->v) x=x->s[0];
			else x=x->s[1];
		}
		
		int k=!(v<y->v);
		y->s[k]=newnode(y,v);
		splay(y->s[k]);
	}
	
	
	node*Find(int v)
	{
		node*x=root;
		node*y=x;
		node*r=nil;
		while(x!=nil)
		{
			y=x;
			if(x->v==v) r=x;
			if(v<=x->v) x=x->s[0];
			else x=x->s[1];
		}
		splay(y);
		return r;
	}
	
	node* FindRank(int k)
	{
		node*x=root;
		node*y=x;
		while(x!=nil)
		{
			y=x;
			if(k==x->s[0]->tot+1) break;
			
			if(k<x->s[0]->tot+1)
				x=x->s[0];
			else
			{
				k-=x->s[0]->tot+1;
				x=x->s[1];
			}
		}
		splay(y);
		return x;
	}
	
	int GetRank(node*x)
	{
		splay(x);
		return x->s[0]->tot+1;
	}
	
	int GetRevRank(node*x)
	{
		splay(x);
		return x->s[1]->tot+1;
	}
	
	node*Delete(node*x)
	{
		int k=GetRank(x);
		node*L=FindRank(k-1);
		node*R=FindRank(k+1);
		
		splay(L);
		splay(R,L);
		
		if(L==nil && R==nil) root=nil;
		else if(R==nil) L->s[1]=nil;
		else R->s[0]=nil;
		
		if(R!=nil) update(R);
		if(L!=nil) update(L);
		
		return x;
	}
	
	node*prefix(int v)
	{
		node*x=root;
		node*y=x;
		node*r=nil;
		while(x!=nil)
		{
			y=x;
			if(x->v<v) r=x;
			if(v<=x->v) x=x->s[0];
			else x=x->s[1];
		}
		splay(y);
		return r;
	}
	
	node*suffix(int v)
	{
		node*x=root;
		node*y=x;
		node*r=nil;
		while(x!=nil)
		{
			y=x;
			if(x->v>v) r=x;
			if(v<x->v) x=x->s[0];
			else x=x->s[1];
		}
		splay(y);
		return r;
	}
	
	
	
	
	//===========================================
	void output() { output(root); printf("%s\n",root==nil ? "empty tree!" : ""
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值