@KirinBill
2017-09-18T04:27:43.000000Z
字数 9859
阅读 2814
学习笔记 数据结构
目录
split()和合并merge(),一些约定:记为的随机优先级,为的权值,等类似。这里的Treap是小根堆。
底层函数:
建树。。。
按值的大小或序列顺序将Treap分为两个,返回两个根(即左树的节点值小于等于某个值,或左树节点为维护的序列的前k个)。
对于递归后的返回值,若从左子树递归返回,说明可能因分裂被修改,应让。而后因为是当前子树的根,作为的父亲,替代了,应让而后返回。从右子树递归返回类似。
代码:
//按值的大小分裂dual_rt split(int u,int val){dual_rt ret(0,0);if(!u) return ret;if(val<d[u].val){ret=split(d[u].ls,val);d[u].ls=ret.rrt;ret.rrt=u;}else{ret=split(d[u].rs,val);d[u].rs=ret.lrt;ret.lrt=u;}upd(u);return ret;}
//按序列顺序分裂dual_rt split(int u,int k){dual_rt ret(0,0);if(!u) return ret;push_d(u); //区间翻转的tagif(k<=d[d[u].ls].sz){ret=split(d[u].ls,k);d[u].ls=ret.rrt;ret.rrt=u;}else{ret=split(d[u].rs,k-d[d[u].ls].sz-1);d[u].rs=ret.lrt;ret.lrt=u;}upd(u);return ret;}
给定两个相对有序的Treap(任意左树节点的值都严格小于右树节点的值,或任意左树节点的在维护的原序列中的位置都严格小于右树节点),将其合并为一个Treap,返回合并后Treap的根。
代码:
int merge(int u,int v){if(!u) return v;else if(!v) return u;if(d[u].key<d[v].key){d[u].rs=merge(d[u].rs,v);upd(u);return u;}else{d[v].ls=merge(u,d[v].ls);upd(v);return v;}}
新建一个节点,并返回该节点标号。
太简单了,就不说了...
代码:
int new_nd(int val){static int cnt=0;d[++cnt].val=val;d[cnt].key=rand();d[cnt].sz=1;return cnt;}
功能函数:
在Treap中插入一个节点。
先将Treap在要插入的位置Split开,再NewNode一个节点并将三个Treap按顺序Merge起来。
代码:
void ist(int val){dual_rt x=split(rt,val);rt=merge(merge(x.lrt,new_nd(val)),x.rrt);}
在Treap中删除一个节点。
其实,非旋转式Treap还可以做到一般平衡树做不到的删除一段连续的值(做法类似)。
代码:
void del(int val){dual_rt x=split(rt,val);dual_rt y=split(x.lrt,val-1);y.rrt=merge(d[y.rrt].ls,d[y.rrt].rs);rt=merge(merge(y.lrt,y.rrt),x.rrt);}
查询一个值在Treap中的排名。
然后就等于左边Treap的大小加.
代码:
int get_rk(int val){dual_rt x=split(rt,val-1);int ret=d[x.lrt].sz+1;rt=merge(x.lrt,x.rrt);return ret;}
查询Treap中排名为k的值。
和正常的Treap操作一样,不细讲了...
代码:
int kth_val(int u,int k){while(true){if(k<=d[d[u].ls].sz)u=d[u].ls;else if(d[d[u].ls].sz+1<k){k-=d[d[u].ls].sz+1;u=d[u].rs;}else break;}return d[u].val;}//函数重载了一次(上面的函数还有别的用途)int kth_val(int k){return kth_val(rt,k);}
查询一个值在Treap中的前驱。
注意:有的题需要特判不存在前趋的情况!
代码:
//用到了上面kth_val的第一个函数int pred(int val){dual_rt x=split(rt,val-1);int ret=kth_val(x.lrt,d[x.lrt].sz);rt=merge(x.lrt,x.rrt);return ret;}
查询一个值在Treap中的后继。
和查询前驱类似,不说了(也要注意有的题要特判不存在后继的情况)。
代码:
int succ(int val){dual_rt x=split(rt,val);int ret=kth_val(x.rrt,1);rt=merge(x.lrt,x.rrt);return ret;}
对于维护序列的Treap来说,将该序列中某一个区间反转一下。
push_d();其它对序列的操作都类似,Splay能做的除了LCT,非旋转式Treap都可以!
代码:
void rvs(int l,int r){dual_rt x=split(rt,l-1);dual_rt y=split(x.rrt,r-l+1);d[y.lrt].rev^=true;rt=merge(merge(x.lrt,y.lrt),y.rrt);}
代码:
#include <cstdio>#include <cstdlib>#include <utility>#define lrt first#define rrt secondusing std::pair;typedef pair<int,int> dual_rt;const int MAXN=100005;struct node{int ls,rs,val,key,sz;friend bool operator< (const node &a,const node &b){return a.val<b.val;}};class FHQ_Treap{private:int rt;node d[MAXN];void upd(int u){d[u].sz=d[d[u].ls].sz+d[d[u].rs].sz+1;}int new_nd(int val){static int cnt=0;d[++cnt].val=val;d[cnt].key=rand();d[cnt].sz=1;return cnt;}dual_rt split(int u,int val){dual_rt ret(0,0);if(!u) return ret;if(val<d[u].val){ret=split(d[u].ls,val);d[u].ls=ret.rrt;ret.rrt=u;}else{ret=split(d[u].rs,val);d[u].rs=ret.lrt;ret.lrt=u;}upd(u);return ret;}int merge(int u,int v){if(!u) return v;else if(!v) return u;if(d[u].key<d[v].key){d[u].rs=merge(d[u].rs,v);upd(u);return u;}else{d[v].ls=merge(u,d[v].ls);upd(v);return v;}}int kth_val(int u,int k){while(true){if(k<=d[d[u].ls].sz)u=d[u].ls;else if(d[d[u].ls].sz+1<k){k-=d[d[u].ls].sz+1;u=d[u].rs;}else break;}return d[u].val;}public:void ist(int val){dual_rt x=split(rt,val);rt=merge(merge(x.lrt,new_nd(val)),x.rrt);}void del(int val){dual_rt x=split(rt,val);dual_rt y=split(x.lrt,val-1);y.rrt=merge(d[y.rrt].ls,d[y.rrt].rs);rt=merge(merge(y.lrt,y.rrt),x.rrt);}int get_rk(int val){dual_rt x=split(rt,val-1);int ret=d[x.lrt].sz+1;rt=merge(x.lrt,x.rrt);return ret;}int kth_val(int k){return kth_val(rt,k);}int pred(int val){dual_rt x=split(rt,val-1);int ret=kth_val(x.lrt,d[x.lrt].sz);rt=merge(x.lrt,x.rrt);return ret;}int succ(int val){dual_rt x=split(rt,val);int ret=kth_val(x.rrt,1);rt=merge(x.lrt,x.rrt);return ret;}}T;int main(){int n;scanf("%d",&n);for(int i=1,opt,x;i<=n;++i){scanf("%d%d",&opt,&x);switch(opt){case 1: T.ist(x); break;case 2: T.del(x); break;case 3: printf("%d\n",T.get_rk(x));break;case 4: printf("%d\n",T.kth_val(x));break;case 5: printf("%d\n",T.pred(x));break;default:printf("%d\n",T.succ(x));}}return 0;}
代码:
#include <cstdio>#include <cstdlib>#include <algorithm>#include <utility>#include <stack>#define lrt first#define rrt secondusing std::swap;using std::pair;using std::stack;typedef pair<int,int> dual_rt;const int MAXN=100005;int tmp[MAXN];struct node{int s[2],sz,val,key;bool rev;};class seq_Treap{private:int rt;node d[MAXN];void upd(int u){d[u].sz=d[d[u].s[0]].sz+d[d[u].s[1]].sz+1;}void push_d(int u){if(d[u].rev){swap(d[u].s[0],d[u].s[1]);d[d[u].s[0]].rev^=true;d[d[u].s[1]].rev^=true;d[u].rev=false;}}dual_rt split(int u,int k){dual_rt ret(0,0);if(!u) return ret;push_d(u);if(k<=d[d[u].s[0]].sz){ret=split(d[u].s[0],k);d[u].s[0]=ret.rrt;ret.rrt=u;}else{ret=split(d[u].s[1],k-d[d[u].s[0]].sz-1);d[u].s[1]=ret.lrt;ret.lrt=u;}upd(u);return ret;}int merge(int u,int v){if(!u) return v;push_d(u);if(!v) return u;push_d(v);if(d[u].key<d[v].key){d[u].s[1]=merge(d[u].s[1],v);upd(u);return u;}else{d[v].s[0]=merge(u,d[v].s[0]);upd(v);return v;}}void inorder_prt(int u){push_d(u);if(d[u].s[0]) inorder_prt(d[u].s[0]);printf("%d ",d[u].val);if(d[u].s[1]) inorder_prt(d[u].s[1]);}public:void build(int n,int a[]){static stack<int> stk;stk.push(0);for(int i=1,fa;i<=n;++i){d[i].val=a[i];d[i].key=rand();d[i].sz=1;while(fa=stk.top(),d[fa].key>d[i].key){upd(fa);stk.pop();}d[i].s[0]=d[fa].s[1];d[fa].s[1]=i;stk.push(i);}while(stk.size()>1){upd(stk.top());stk.pop();}stk.pop();rt=d[0].s[1];}void rvs(int l,int r){dual_rt x=split(rt,l-1);dual_rt y=split(x.rrt,r-l+1);d[y.lrt].rev^=true;rt=merge(merge(x.lrt,y.lrt),y.rrt);}void prt(){inorder_prt(rt);}}T;int main(){int n,m;scanf("%d%d",&n,&m);for(int i=1;i<=n;++i)tmp[i]=i;T.build(n,tmp);for(int i=1,l,r;i<=m;++i){scanf("%d%d",&l,&r);T.rvs(l,r);}T.prt();return 0;}
代码:
#include <cstdio>#include <cctype>#include <string>using std::string;inline void setIO(string file){string in=file+".in",out=file+".out";freopen(in.c_str(),"r",stdin);freopen(out.c_str(),"w",stdout);}template<typename type>inline void read(type &x){x=0;int pm=1; char c;do{c=getchar();}while(!isdigit(c) && c!='-');c=='-' ? pm=-1:x=c^'0';while(c=getchar(),isdigit(c))x=x*10+(c^'0');x*=pm;}template<typename type>void write(type x,char c=0){if(x<0) putchar('-'),x=-x;if(x>9) write(x/10);putchar(x%10|'0');if(c) putchar(c);}#include <cstdlib>#include <climits>const int MAXN=200005;int n,L,tt;class FHQ_Treap{private:int rt,cnt;struct dual_rt{int lrt,rrt;};struct node{int ls,rs,val,key,sz;}d[MAXN];int new_nd(int val){d[++cnt].val=val;d[cnt].key=rand();d[cnt].sz=1;return cnt;}void upd(int u){d[u].sz=d[d[u].ls].sz+d[d[u].rs].sz+1;}dual_rt split(int u,int val){dual_rt ret=(dual_rt){0,0};if(!u) return ret;if(val<d[u].val){ret=split(d[u].ls,val);d[u].ls=ret.rrt;ret.rrt=u;}else{ret=split(d[u].rs,val);d[u].rs=ret.lrt;ret.lrt=u;}upd(u);return ret;}int merge(int u,int v){if(!u) return v;else if(!v) return u;if(d[u].key<d[v].key){d[u].rs=merge(d[u].rs,v);upd(u);return u;}else{d[v].ls=merge(u,d[v].ls);upd(v);return v;}}int kth_val(int u,int k){if(!k) return -1;while(true){if(k<=d[d[u].ls].sz) u=d[u].ls;else if(k>d[d[u].ls].sz+1){k-=d[d[u].ls].sz+1;u=d[u].rs;}else return d[u].val;}}public:void ist(int val){dual_rt x=split(rt,val);rt=merge(merge(x.lrt,new_nd(val)),x.rrt);}void del(int lval,int rval){dual_rt x=split(rt,lval);dual_rt y=split(x.rrt,rval-1);rt=merge(x.lrt,y.rrt);}int lge_cnt(int val){dual_rt x=split(rt,val);int ret=d[x.rrt].sz;rt=merge(x.lrt,x.rrt);return ret;}int geq_cnt(int val){dual_rt x=split(rt,val-1);int ret=d[x.rrt].sz;rt=merge(x.lrt,x.rrt);return ret;}int pred(int val){dual_rt x=split(rt,val-1);int ret=kth_val(x.lrt,d[x.lrt].sz);rt=merge(x.lrt,x.rrt);return ret==0 ? INT_MIN:ret;}int succ(int val){dual_rt x=split(rt,val);int ret=kth_val(x.rrt,1);rt=merge(x.lrt,x.rrt);return ret==0 ? INT_MAX:ret;}}lp,rp;inline int add(int l,int r){static int ret=0;ret-=rp.geq_cnt(l)-lp.lge_cnt(r);++ret;lp.del(rp.pred(l),r+1);lp.ist(l);rp.del(l-1,lp.succ(r));rp.ist(r);return ret;}int main(){setIO("poster");read(L),read(n),read(tt);if(tt){for(int i=1,x,y,lastans=0;i<=n;++i){read(x),read(y);x^=lastans,y^=lastans;lastans=add(x,y);write(lastans,'\n');}}else{for(int i=1,x,y;i<=n;++i){read(x),read(y);write(add(x,y),'\n');}}return 0;}