刷了一些平衡树的题,基本都是用无旋treap写的(比splay好写的多),贴一些题目中经常用到的函数。。
1.merge(最基本的)
int mg(int x,int y)
{
if(!x||!y)return x+y;
if(node[x].rnd<=node[y].rnd)
{
node[y].ls=mg(x,node[y].ls);
push_up(y);
return y;
}
else
{
node[x].rs=mg(node[x].rs,y);
push_up(x);
return x;
}
}
2.split1(按sz切)
if(!nw)x=y=0;
else
{
if(node[node[nw].ls].sz>=k)y=nw,split1(node[nw].ls,k,x,node[nw].ls);
else x=nw,split1(node[nw].rs,k-node[node[nw].ls].sz-1,node[nw].rs,y);
push_up(nw);
}
3.split2(按权值切)
if(!nw)x=y=0;
else
{
if(node[nw].w<=k)x=nw,split2(node[nw].rs,k,node[nw].rs,y);
else y=nw,split2(node[nw].ls,k,x,node[nw].ls);
push_up(nw);
}
4.维护父亲节点(可以方便的在treap上乱走。。)
void push_up(int x)
{if(l)node[l].fa=x;if(r)node[r].fa=x;}//在mg,split时的push_up里加这行就可以
5.查找某点在所在treap排名(需要先维护fa)
int ask(int x)
{
static int ans;
ans=node[node[x].ls].sz+1;
while(node[x].fa)
{
if(x==node[node[x].fa].rs)
{
x=node[x].fa;
ans+=node[node[x].ls].sz+1;
}
else x=node[x].fa;
}
return ans;
}
6.insert(按大小插入)
void insert(int &a,int b)
{
static int x,y;
split2(a,node[b].w,x,y);
a=mg(mg(x,b),y);
}
7.找到节点所在treap的根
int rrr(int x)
{
while(node[x].fa)x=node[x].fa;
return x;
}
8.合并两棵treap(小并大保证复杂度)
void mm(int &a,int b)
{
if(node[b].ls)mm(a,node[b].ls);
if(node[b].rs)mm(a,node[b].rs);
init(b,node[b].w);//注意!!插进去前要初始化孩子父亲等信息!
insert(a,b);
}
void M(int a,int b)
{
a=rrr(a),b=rrr(b);
if(a==b)return;
if(node[a].sz<node[b].sz)swap(a,b);
mm(a,b);
}