非旋转式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);
 }
}
posted @ 2017-02-27 19:09  Krew  阅读(213)  评论(0)    收藏  举报