[模板]Treap

友情链接:一篇写的很好的博客

旋转Treap

#include <cstdio>

int get() {
	int x = 0, f = 1; char s;
	while ((s = getchar()) < '0' || s > '9') if(s == '-') f = -1;
	while (s >= '0' && s <= '9') x = (x << 3) + (x << 1) + (s ^ 48), s = getchar();
	return x * f;
}

void put(int x) {
	if(x < 0) x = -x, putchar('-');
	if(x > 9) put(x / 10);
	putchar(x % 10 ^ 48);
}

int Max(const int x, const int y) {
	if(x > y) return x;
	return y;
}

int Min(const int x, const int y) {
	if(x < y) return x;
	return y;
}

const int MO = 2147483647;

int rand() {
	static int a = 52331314;
	a = a * 33457 % MO;
	return a;
}

const int M = 1e5 + 5, INF = 2e9;
int rt, siz[M], key[M], cnt[M], son[M][2], rd[M], tot;

void pushup(const int x) {
	siz[x] = siz[son[x][0]] + siz[son[x][1]] + cnt[x];
}

void rotate(int &x, const bool y) {
	int i = son[x][y ^ 1];
	son[x][y ^ 1] = son[i][y];
	son[i][y] = x;
	pushup(x);
	pushup(i);
	x = i;
}

void ins(int &x, const int val) {
	if(!x) {
		x = ++tot;
		siz[x] = cnt[x] = 1;
		key[x] = val;
		rd[x] = rand();
		return;
	}
	if(key[x] == val) {
		++cnt[x], ++siz[x];
		return;
	}
	bool d = val > key[x];
	ins(son[x][d], val);
	if(rd[x] < rd[son[x][d]]) rotate(x, d ^ 1);
	pushup(x);
}

void del(int &x, const int val) {
	if(!x) return;
	if(val != key[x]) del(son[x][val > key[x]], val);
	else {
		if(!son[x][0] && !son[x][1]) {
			--cnt[x], --siz[x];
			if(!cnt[x]) x = 0;
		} else if(son[x][0] && !son[x][1]) {
			rotate(x, 1);
			del(son[x][1], val);
		} else if(!son[x][0] && son[x][1]) {
			rotate(x, 0);
			del(son[x][0], val);
		} else {
			bool d = rd[son[x][0]] > rd[son[x][1]];
			rotate(x, d);
			del(son[x][d], val);
		}
	}
	pushup(x);
}

int getrank(const int x, const int val) {
	if(!x) return 0;
	if(key[x] == val)
		return siz[son[x][0]] + 1;
	if(key[x] < val)
		return siz[son[x][0]] + cnt[x] + getrank(son[x][1], val);
	return getrank(son[x][0], val);
}

int Find(const int x, const int val) {
	if(!x) return 0;
	if(siz[son[x][0]] >= val)
		return Find(son[x][0], val);
	if(siz[son[x][0]] + cnt[x] < val)
		return Find(son[x][1], val - cnt[x] - siz[son[x][0]]);
	return key[x];
}

int getpre(const int x, const int val) {
	if(!x) return -INF;
	if(key[x] >= val)
		return getpre(son[x][0], val);
	return Max(key[x], getpre(son[x][1], val));
}

int getsuc(const int x, const int val) {
	if(!x) return INF;
	if(key[x] <= val)
		return getsuc(son[x][1], val);
	return Min(key[x], getsuc(son[x][0], val));
}

int main() {
	
	return 0;
}

FHQ_Treap

#include <cstdio>

int get() {
	int x = 0, f = 1; char s;
	while ((s = getchar()) < '0' || s > '9') if(s == '-') f = -1;
	while (s >= '0' && s <= '9') x = (x << 3) + (x << 1) + (s ^ 48), s = getchar();
	return x * f;
}

void put(int x) {
	if(x < 0) x = -x, putchar('-');
	if(x > 9) put(x / 10);
	putchar(x % 10 ^ 48);
}

const int MO = 2147483647;

int rand() {
	static int a = 52331314;
	a = a * 33457 % MO;
	return a;
}

const int M = 1e5 + 5;;
int root, cnts, son[M][2], keyof[M], cnt[M], rd[M], siz[M];
struct Npair {
    int p[2];
};

void pushup(const int x) {
	siz[x] = cnt[x] + siz[son[x][0]] + siz[son[x][1]];
}

int newnode(const int nowk, const int val) {
	++cnts;
	son[cnts][0] = son[cnts][1] = 0;
	siz[cnts] = cnt[cnts] = val;
	keyof[cnts] = nowk;
	rd[cnts] = rand();
	return cnts;
}

Npair spli(const int x,int nowk) {
    Npair ans;
    ans.p[0] = ans.p[1] = 0;
    if(x) {
        int d = keyof[x] <= nowk;
        ans = spli(son[x][d], nowk);
        son[x][d] = ans.p[d ^ 1];
        pushup(x);
        ans.p[d ^ 1] = x;
    }
    return ans;
}

int merg(const int x1, const int x2) {
    if(!x1) return x2;
    if(!x2) return x1;
    if(rd[x1] < rd[x2]) {
        son[x1][1] = merg(son[x1][1], x2);
        pushup(x1);
        return x1;
    } else {
        son[x2][0] = merg(x1, son[x2][0]);
        pushup(x2);
        return x2;
    }
}

int ins(const int x, const int nowk) {
    Npair temp1 = spli(x, nowk);
    Npair temp0 = spli(temp1.p[0], nowk - 1);
    if(temp0.p[1]) {
        ++cnt[temp0.p[1]];
        pushup(temp0.p[1]);
        return merg(merg(temp0.p[0], temp0.p[1]), temp1.p[1]);
    }
    return merg(merg(temp0.p[0], newnode(nowk,1)), temp1.p[1]);
}

int del(const int x, const int nowk) {
    Npair temp1 = spli(x, nowk);
    Npair temp0 = spli(temp1.p[0], nowk - 1);
    if(temp0.p[1] && cnt[temp0.p[1]] > 1) {
        --cnt[temp0.p[1]];
        pushup(temp0.p[1]);
        return merg(merg(temp0.p[0], temp0.p[1]), temp1.p[1]);
    }
    return merg(temp0.p[0], temp1.p[1]);
}

int getrank(const int x, const int nowk) {
	if(!x) return 0;
	if(siz[son[x][0]] < nowk && siz[son[x][0]] + cnt[x] >= nowk)
		return x;
	if(siz[son[x][0]] >= nowk)
		return getrank(son[x][0], nowk);
	return getrank(son[x][1], nowk - siz[son[x][0]] - cnt[x]);
}

int getkey(const int x, const int nowk) {
	int now;
	if(!x) now = 1;
	else if(keyof[x] == nowk) now = siz[son[x][0]] + 1;
	else if(keyof[x] > nowk) now = getkey(son[x][0], nowk);
	else now = getkey(son[x][1], nowk) + siz[son[x][0]] + cnt[x];
	return now;
}

int getpre(const int nowk) {
	int temp = getkey(root, nowk);
	return getrank(root, temp - 1);
}

int getsuc(const int nowk) {
	int temp = getkey(root, nowk);
	int tempd = getrank(root, temp);
	if(keyof[tempd] == nowk)
		return getrank(root, temp + cnt[tempd]);
	else return getrank(root, temp);
}

int main() {
	
	return 0;
}

FHQ_Treap(注释版)

#include<bits/stdc++.h>
using namespace std;

int root;//根
int cnts;//总地址数
int son[100005][2];//son[x][0]左儿子,son[x][1]右儿子
int keyof[100005];//keyof[x]键值
int cnt[100005];//cnt[x]单节点大小
int rd[100005];//rd[x]修正值,根的修正值小
int siz[100005];//siz[x]子树大小

struct Npair
{
    int p[2];
};

void update(int x)
{
	siz[x]=cnt[x]+siz[son[x][0]]+siz[son[x][1]];
}
int newnode(int nowk,int val)
{
	cnts++;
	son[cnts][0]=son[cnts][1]=0;
	siz[cnts]=cnt[cnts]=val;
	keyof[cnts]=nowk;
	rd[cnts]=rand();
	return cnts;
}
Npair spli(int x,int nowk)//按键值分裂,返回两棵树的根
{
    Npair ans;
    ans.p[0]=ans.p[1]=0;
    if(x)
    {
        int d=(keyof[x]<=nowk);
        ans=spli(son[x][d],nowk);
        son[x][d]=ans.p[!d];
        update(x);
        ans.p[!d]=x;
    }
    return ans;
}
int merg(int x1,int x2)//合并,返回新树的根
{
    if(x1==0)
        return x2;
    if(x2==0)
        return x1;
    if(rd[x1]<rd[x2])
    {
        son[x1][1]=merg(son[x1][1],x2);
        update(x1);
        return x1;
    }
    else
    {
        son[x2][0]=merg(x1,son[x2][0]);
        update(x2);
        return x2;
    }
}
int ins(int x,int nowk)//插入
{
    Npair temp1=spli(x,nowk);
    Npair temp0=spli(temp1.p[0],nowk-1);
    if(temp0.p[1])
    {
        cnt[temp0.p[1]]++;
        update(temp0.p[1]);
        return merg(merg(temp0.p[0],temp0.p[1]),temp1.p[1]);
    }
    return merg(merg(temp0.p[0],newnode(nowk,1)),temp1.p[1]);
}
int del(int x,int nowk)//删除
{
    Npair temp1=spli(x,nowk);
    Npair temp0=spli(temp1.p[0],nowk-1);
    if(temp0.p[1] && cnt[temp0.p[1]]>1)
    {
        cnt[temp0.p[1]]--;
        update(temp0.p[1]);
        return merg(merg(temp0.p[0],temp0.p[1]),temp1.p[1]);
    }
    return merg(temp0.p[0],temp1.p[1]);
}
int fkth(int x,int nowk)//返回第k大的点的地址 0表示没找到
{
	if(x==0)
		return 0;
	if(siz[son[x][0]]<nowk && siz[son[x][0]]+cnt[x]>=nowk)
		return x;
	if(siz[son[x][0]]>=nowk)
		return fkth(son[x][0],nowk);
	return fkth(son[x][1],nowk-siz[son[x][0]]-cnt[x]);
}
int fkey(int x,int nowk)//返回同键值最小排名 没找到的话返回假设存在的排名
{
	int now;
	if(x==0)
		now= 1;
	else if(keyof[x]==nowk)
		now= siz[son[x][0]]+1;
	else if(keyof[x]>nowk)
		now= fkey(son[x][0],nowk);
	else
		now= fkey(son[x][1],nowk)+siz[son[x][0]]+cnt[x];
	return now;
}
int pre(int nowk)//返回前驱地址
{
	int temp=fkey(root,nowk);
	return fkth(root,temp-1);
}
int nex(int nowk)//返回后继地址
{
	int temp=fkey(root,nowk);
	int tempd=fkth(root,temp);
	if(keyof[tempd]==nowk)
		return fkth(root,temp+cnt[tempd]);
	else
		return fkth(root,temp);
}

int main()
{
	srand(52331314 + 'T' + 'o' + 'k' + 'i' + 's' + 'a' + 'k' + 'i' + 'K' + 'u' + 'r' + 'u' + 'm' + 'i');
	int n,t,x;
	scanf("%d",&n);
	while(n--)
	{
		scanf("%d%d",&t,&x);
		if(t==1)
			root=ins(root,x);
		if(t==2)
			root=del(root,x);
		if(t==3)
			printf("%d\n",fkey(root,x));
		if(t==4)
			printf("%d\n",keyof[fkth(root,x)]);
		if(t==5)
			printf("%d\n",keyof[pre(x)]);
		if(t==6)
			printf("%d\n",keyof[nex(x)]);
	for (int i = 1; i <= n; ++i)
	}
	return 0;
}

例题

1.普通平衡树

#include<bits/stdc++.h>
using namespace std;

int cnts;//总地址数
int son[100005][2];//son[x][0]左儿子,son[x][1]右儿子
int keyof[100005];//keyof[x]键值
int valof[100005];//valof[x]权值
int rd[100005];//rd[x]修正值,根的修正值小
int siz[100005];//siz[x]子树大小

struct Npair
{
    int p[2];
};

void pushdown(int x)
{
}
void update(int x)
{
	siz[x]=1+siz[son[x][0]]+siz[son[x][1]];
}
int randd()
{
	return (rand()*6666)&rand();
}
int newnode(int nowk,int val)
{
	cnts++;
	son[cnts][0]=son[cnts][1]=0;
	siz[cnts]=1;
	valof[cnts]=val;
	keyof[cnts]=nowk;
	rd[cnts]=randd();
	return cnts;
}
Npair spli(int x,int nowk,bool flag)//分裂,返回两棵树的根,flag表示分裂依据,0按键值1按排名
{
    Npair ans;
    ans.p[0]=ans.p[1]=0;
    if(x)
    {
    	int d;
    	if(flag)
        	d=(siz[son[x][0]]+1<=nowk);
        else
			d=(keyof[x]<=nowk);
		pushdown(x);
		if(flag && d)
        	ans=spli(son[x][d],nowk-siz[son[x][0]]-1,flag);
        else
			ans=spli(son[x][d],nowk,flag);
        son[x][d]=ans.p[!d];
        update(x);
        ans.p[!d]=x;
    }
    return ans;
}
int merg(int x1,int x2)//合并,返回新树的根
{
    if(x1==0)
        return x2;
    if(x2==0)
        return x1;
    if(rd[x1]<rd[x2])
    {
    	pushdown(x1);
        son[x1][1]=merg(son[x1][1],x2);
        update(x1);
        return x1;
    }
    else
    {
    	pushdown(x2);
        son[x2][0]=merg(x1,son[x2][0]);
        update(x2);
        return x2;
    }
}
int ins(int x,int nowk,int val=0)//插入
{
    Npair temp=spli(x,nowk,0);
    temp.p[0]=merg(temp.p[0],newnode(nowk,val));
    return merg(temp.p[0],temp.p[1]);
}
int del(int x,int nowk)//删除
{
    Npair temp1=spli(x,nowk,0);
    int temp=siz[temp1.p[0]]-1;
    Npair temp0=spli(temp1.p[0],temp,1);
    if(keyof[temp0.p[1]]!=nowk)
    	temp0.p[0]=merg(temp0.p[0],temp0.p[1]);
    return merg(temp0.p[0],temp1.p[1]);
}
int fkth(int x,int nowk)//返回第k大的点的地址 0表示没找到
{
	Npair temp1=spli(x,nowk,1);
    Npair temp0=spli(temp1.p[0],nowk-1,1);
    int now=temp0.p[1];
    temp1.p[0]=merg(temp0.p[0],temp0.p[1]);
    merg(temp1.p[0],temp1.p[1]);
    return now;
}
int fkey(int x,int nowk)//返回同键值最小排名 没找到的话返回假设存在的排名
{
	Npair temp=spli(x,nowk-1,0);
    int now=siz[temp.p[0]]+1;
    merg(temp.p[0],temp.p[1]);
    return now;
}
int pre(int x,int nowk)//返回前驱地址
{
	Npair temp1=spli(x,nowk-1,0);
	int temp=siz[temp1.p[0]]-1;
	Npair temp0=spli(temp1.p[0],temp,1);
	int now=temp0.p[1];
	temp1.p[0]=merg(temp0.p[0],temp0.p[1]);
    merg(temp1.p[0],temp1.p[1]);
	return now;
}
int nex(int x,int nowk)//返回后继地址
{
	Npair temp0=spli(x,nowk,0);
	Npair temp1=spli(temp0.p[1],1,1);
	int now=temp1.p[0];
	temp0.p[1]=merg(temp1.p[0],temp1.p[1]);
	merg(temp0.p[0],temp0.p[1]);
	return now;
}

int main()
{
	int n,t,x,root=0;
	scanf("%d",&n);
	while(n--)
	{
		scanf("%d%d",&t,&x);
		if(t==1)
			root=ins(root,x);
		if(t==2)
			root=del(root,x);
		if(t==3)
			printf("%d\n",fkey(root,x));
		if(t==4)
			printf("%d\n",keyof[fkth(root,x)]);
		if(t==5)
			printf("%d\n",keyof[pre(root,x)]);
		if(t==6)
			printf("%d\n",keyof[nex(root,x)]);
	}
	return 0;
}

2.文艺平衡树

#include<bits/stdc++.h>
using namespace std;

stack <int> q;

int son[100005][2];//son[x][0]左儿子,son[x][1]右儿子
int valof[100005];//valof[x]权值
int rd[100005];//rd[x]修正值,根的修正值小
int siz[100005];//siz[x]子树大小
bool flag[100005];//flag[x]翻转标记

struct Npair
{
    int p[2];
};

void change(int x)
{
    if(x)
    {
        int t;
        flag[x]=!flag[x];
        t=son[x][0];
        son[x][0]=son[x][1];
        son[x][1]=t;
    }
}
void pushdown(int x)
{
    if(flag[x])
    {
        change(son[x][0]);
        change(son[x][1]);
        flag[x]=0;
    }
}
void update(int x)
{
	siz[x]=1+siz[son[x][0]]+siz[son[x][1]];
}
int randd()
{
    int x=(rand()*6666)&rand();
	return x;
}
Npair spli(int x,int nowk)//按排名分裂,返回两棵树的根
{
    Npair ans;
    ans.p[0]=ans.p[1]=0;
    if(x)
    {
    	int d;
    	d=(siz[son[x][0]]+1<=nowk);
		pushdown(x);
		if(d)
        	ans=spli(son[x][d],nowk-siz[son[x][0]]-1);
        else
			ans=spli(son[x][d],nowk);
        son[x][d]=ans.p[!d];
        update(x);
        ans.p[!d]=x;
    }
    return ans;
}
int merg(int x1,int x2)//合并,返回新树的根
{
    if(x1==0)
        return x2;
    if(x2==0)
        return x1;
    if(rd[x1]<rd[x2])
    {
    	pushdown(x1);
        son[x1][1]=merg(son[x1][1],x2);
        update(x1);
        return x1;
    }
    else
    {
    	pushdown(x2);
        son[x2][0]=merg(x1,son[x2][0]);
        update(x2);
        return x2;
    }
}
void out(int x)
{
    pushdown(x);
    if(son[x][0])
        out(son[x][0]);
    printf("%d ",valof[x]);
    if(son[x][1])
        out(son[x][1]);
}
void ask(int x)
{
    if(!x)
        return;
    ask(son[x][0]);
    ask(son[x][1]);
    update(x);
}
int swaps(int x,int l,int r)
{
    Npair temp1=spli(x,r);
    Npair temp0=spli(temp1.p[0],l-1);
    change(temp0.p[1]);
    temp1.p[0]=merg(temp0.p[0],temp0.p[1]);
    return merg(temp1.p[0],temp1.p[1]);
}
int main()
{
	int root,temp,n,m,l,r;
	scanf("%d%d",&n,&m);
	q.push(0);
	rd[0]=-1;
	for(int i=1;i<=n;i++)
    {
        valof[i]=i;
        rd[i]=randd();
        temp=0;
        while(rd[i]<rd[q.top()])
        {
            temp=q.top();
            q.pop();
        }
        son[q.top()][1]=i;
        son[i][0]=temp;
        q.push(i);
    }
    root=son[0][1];
    son[0][1]=0;
    ask(root);
    while(m--)
    {
        scanf("%d%d",&l,&r);
        root=swaps(root,l,r);
    }
    out(root);
	return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值