树堆的典型范例
二叉排序树+堆
所有操作围绕merge
跟split
两个操作进行
treep跟i笛卡尔树的结构上是相同的,只是两者的应用不同,treap的Value是随机值,为了使树更加平衡引起的,而笛卡尔树的value是一个确定值。
不懂笛卡尔树的可以看这
传送们
#include<iostream>
#include<sstream>
#include<queue>
#include<vector>
#include<ctime>
#include<cstdlib>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn=50005;
struct node;
node *null,*root[maxn];
struct node
{
node* c[2];
char v;
int r,sz;
void up(){
sz=c[0]->sz+c[1]->sz+1;
}
node(char v=0):v(v){
sz=1;
r=rand();
c[0]=c[1]=null;
}
};
inline void copy(node* &a,node* b)
{
if(b==null){
a=b;
}
else a=new node(),*a=*b;
}
void merge(node* &o,node* a,node *b)
{
if(a==null)
copy(o,b);
else if(b==null)
copy(o,a);
else if(a->r<b->r){
copy(o,a);
merge(o->c[1],a->c[1],b);
o->up();
}
else{
copy(o,b);
merge(o->c[0],a,b->c[0]);
o->up();
}
}
void split(node* o,node* &a,node* &b,int k)//将树堆o的前k个节点变为数堆a,剩下节点变为数堆b,
{
if(!k){
copy(b,o);
a=null;
}
else if(o->sz<=k){
copy(a,o);
b=null;
}else if(o->c[0]->sz>=k){
copy(b,o);
split(o->c[0],a,b->c[0],k);
b->up();
}else{
copy(a,o);
split(o->c[1],a->c[1],b,k-o->c[0]->sz-1);
a->up();
}
}
char s[203];
void build(node* &o,int l,int r)
{
if(l>r)
return;
int m=(l+r)>>1;
o=new node(s[m]);
build(o->c[0],l,m-1);
build(o->c[1],m+1,r);
o->up();
}
void ins(node* &o,node* pre,int pos) // 在pre的pos位置插入字串s,形成新树堆o
{
node *a,*b,*c;
int len=strlen(s);
split(pre,a,b,pos);
build(c,0,len-1);
merge(a,a,c);
merge(o,a,b);
}
void del(node* &o,node* pre,int pos,int len)
{
node *a,*b,*c;
split(pre,a,b,pos-1);
split(b,b,c,len);
merge(o,a,c);
}
int dlt; //字符c的个数
void out(node* o)
{
if(o==null) return ;
out(o->c[0]);
if(o->v=='c') dlt++;
printf("%c",o->v);
out(o->c[1]);
}
void out(node *o,int pos,int len) //输出树堆o中从pos位置开始的len个字符。
{
node *a,*b,*c;
split(o,a,b,pos-1);
split(b,b,c,len);
out(b);
puts("");
}
void init()
{
null=new node();
null->sz=0;
for(int i=0;i<maxn;i++)
root[i]=null;
}
int n;
int main()
{
scanf("%d",&n);
init();
int op,pos,len,v,nowv=0;
while(n--){
scanf("%d",&op);
if(op==1){
scanf("%d%s",&pos,s);
pos-=dlt;
ins(root[nowv+1],root[nowv],pos);
nowv++;
}else if(op==2){
scanf("%d%d",&pos,&len);
pos-=dlt;len-=dlt;
del(root[nowv+1],root[nowv],pos,len);
nowv++;
}else{
scanf("%d%d%d",&v,&pos,&len);
v-=dlt;pos-=dlt;len-=dlt;
out(root[v],pos,len);
}
}
return 0;
}
/*
6
1 0 abcdefgh
2 4 3
3 1 2 5
3 3 3 4
1 4 xy
3 5 4 6
*/