@KirinBill
2017-09-18T12:27:43.000000Z
字数 9859
阅读 2229
学习笔记
数据结构
目录
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); //区间翻转的tag
if(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 second
using 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 second
using 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;
}