非旋转式Treap
传统式的Treap通过旋转来保证查找效率,但这样有一个不好:旋转会破环树的形态,导致无法高效的在上面维护标记。而非旋转的Treap就没有这种问题,它通过分裂和合并操作来进行维护而不是旋转。
支持的操作:
- merge(x,y):将两棵根节点分别为x,y的树合并,返回新的树的根
- split(x,k):将以x为根的树的前k个结点和其他结点分别划分到两棵树中,返回两棵树的根
拓展的操作:
- insert(x):先split出两段,分三段merge
- delete(x):split出三段,merge两段
- 维护:在一个结点上维护tag
struct Node{
Node *l,*r;
int v,rk,siz,tag;
Node(int v,Node *null):v(v),rk(rand()),l(null),r(null),siz(1),tag(0) {}
void maintain() {siz=l->siz+r->siz+1;}
void pushdown() {if (tag) l->tag+=tag,r->tag+=tag,v+=tag,tag=0;}
} *null,*root;
typedef pair<Node*,Node*> pat;
int n,a[maxn],ans;
//---------Still Treap---------
Node *newnode(int v) {return new Node(v,null);}
Node *merge(Node *a,Node *b)
{
if (a==null) return b;
if (b==null) return a;
if (a->rk<b->rk)
{
a->pushdown();
a->r=merge(a->r,b),a->maintain();
return a;
}
else
{
b->pushdown();
b->l=merge(a,b->l),b->maintain();
return b;
}
}
int rank(Node *o,int val)
{
if (o==null) return 0;
if (o->v<=val) return o->l->siz+1+rank(o->r,val); else return rank(o->l,val);
}
pat split(Node *o,int k)
{
if (o==null) return make_pair(null,null);
if (k==0) return make_pair(null,o);
if (k>=o->siz) return make_pair(o,null);
if ((o->l->siz)>=k)
{
pat temp=split(o->l,k);
Node *b=newnode(o->v);b->rk=o->rk;
b->l=temp.second,b->r=o->r,b->maintain();
return make_pair(temp.first,b);
}
else
{
pat temp=split(o->r,k-o->l->siz-1);
newnodee *a=newnode(o->v);a->rk=o->rk;
a->r=temp.first,a->l=o->l,a->maintain();
return make_pair(a,temp.second);
}
}

浙公网安备 33010602011771号