bzoj 3223: Tyvj 1729 文艺平衡树
Description
您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1
Input
第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2……n-1,n) m表示翻转操作次数
接下来m行每行两个数[l,r] 数据保证 1<=l<=r<=n
Output
输出一行n个数字,表示原始序列经过m次变换后的结果
Sample Input
5 3
1 3
1 3
1 4
1 3
1 3
1 4
Sample Output
4 3 2 1 5
HINT
N,M<=100000
平衡树练习题,这题可以有两种做法,splay和fhq treap,我写了fhq treap
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 int const N=100000+10; 4 int ch[N][2],tg[N],root,n,m,sum,val[N],sz[N],key[N]; 5 int mr(int v){ 6 int x=++sum;val[x]=v;ch[x][0]=ch[x][1]=tg[x]=0;key[x]=rand();sz[x]=1; return x; 7 } 8 void update(int x){ 9 sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1; 10 } 11 void pushd(int x){ 12 if(!x) return ; 13 if(tg[x]){ 14 tg[x]^=1; 15 swap(ch[x][0],ch[x][1]); 16 tg[ch[x][0]]^=1; 17 tg[ch[x][1]]^=1; 18 } 19 } 20 int merge(int x,int y){ 21 pushd(x); pushd(y); 22 if(!x || !y) return x+y; 23 if(key[x]<key[y]){ 24 ch[x][1]=merge(ch[x][1],y); 25 update(x); return x; 26 }else { 27 ch[y][0]=merge(x,ch[y][0]); 28 update(y); return y; 29 } 30 } 31 void split(int now,int k,int &x,int &y){ 32 if(!now) x=y=0; 33 else { 34 pushd(now); 35 if(k<=sz[ch[now][0]]) 36 y=now,split(ch[now][0],k,x,ch[y][0]); 37 else 38 x=now,split(ch[now][1],k-sz[ch[now][0]]-1,ch[x][1],y); 39 update(now); 40 } 41 } 42 void dfs(int x){ 43 if(!x) return; 44 pushd(x); 45 dfs(ch[x][0]); 46 if(val[x]!=0 && val[x]!=n+1) printf("%d ",val[x]); 47 dfs(ch[x][1]); 48 } 49 int main(){ 50 scanf("%d%d",&n,&m); 51 for(int i=0;i<=n+1;i++) 52 root=merge(root,mr(i)); 53 while (m--){ 54 int l,r,x,y,z; 55 scanf("%d%d",&l,&r); 56 split(root,r+1,x,y); 57 split(x,l,x,z); 58 tg[z]^=1; 59 root=merge(merge(x,z),y); 60 } 61 dfs(root); 62 return 0; 63 }