传送门
经典的平衡树问题,之前已经用splay写过一次了,今天我突发奇想,写了一发非旋treap的版本,发现挺好写的(虽然跑不过splay)。
代码:
#include<bits/stdc++.h>
#define N 100005
using namespace std;
typedef pair<int,int> res;
int rt=0,n,m,cnt=0,son[N][2],siz[N],val[N],rd[N],rev[N];
inline int read(){
int ans=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
return ans;
}
inline int build(int v){val[++cnt]=v,rd[cnt]=rand(),siz[cnt]=1,son[cnt][0]=son[cnt][1]=0;return cnt;}
inline void pushup(int p){siz[p]=siz[son[p][0]]+siz[son[p][1]]+1;}
inline void pushdown(int p){
if(!rev[p])return;
swap(son[p][0],son[p][1]);
if(son[p][0])rev[son[p][0]]^=1;
if(son[p][1])rev[son[p][1]]^=1;
rev[p]^=1;
}
inline int merge(int a,int b){
if(!a||!b)return a+b;
pushdown(a),pushdown(b);
if(rd[a]<rd[b]){son[a][1]=merge(son[a][1],b),pushup(a);return a;}
son[b][0]=merge(a,son[b][0]),pushup(b);return b;
}
inline res split(int p,int k){
if(!p)return res(0,0);
res ans,tmp;
pushdown(p);
if(siz[son[p][0]]>=k){
tmp=split(son[p][0],k);
son[p][0]=tmp.second,pushup(p);
ans.first=tmp.first,ans.second=p;
return ans;
}
tmp=split(son[p][1],k-siz[son[p][0]]-1);
son[p][1]=tmp.first,pushup(p);
ans.first=p,ans.second=tmp.second;
return ans;
}
inline int rank(int p,int k){
if(!p)return 0;
if(val[p]>k)return rank(son[p][0],k);
return rank(son[p][1],k)+siz[son[p][0]]+1;
}
inline int build(int l,int r){
if(l==r){siz[l]=1,rd[l]=rand(),son[l][0]=son[l][1]=0,val[l]=l;return l;}
int mid=l+r>>1;
return merge(build(l,mid),build(mid+1,r));
}
inline void update(int l,int r){
res x=split(rt,l-1),y=split(x.second,r-l+1);
rev[y.first]^=1;
rt=merge(x.first,merge(y.first,y.second));
}
inline void print(int p){
pushdown(p);
if(son[p][0])print(son[p][0]);
cout<<p<<' ';
if(son[p][1])print(son[p][1]);
}
int main(){
srand(time(NULL));
n=read(),m=read();
rt=build(1,n);
while(m--){
int l=read(),r=read();
update(l,r);
}
print(rt);
return 0;
}