友情链接:一篇写的很好的博客
旋转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;
}