文艺平衡树(区间翻转)
哇,只会fhq treap的我瑟瑟发抖,不能旋转,那怎么区间翻转啊。
QAQ
仔细一想(看了博客)发现十分简单,也还是暴力拆,只不过用tag标记,交换子树就好了还是很简单的吗
至于不会fhq treap的同学可以先点这里或上 Patrickpwq大佬的博客
1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<ctime> 7 using namespace std; 8 const int maxn=100010; 9 int n,m,val[maxn],rnd[maxn],son[maxn][3],size[maxn],sum_p; 10 int tag[maxn],root=0; 11 inline void read(int &x) 12 { 13 x=0; 14 int f=1; 15 char ch=getchar(); 16 while(ch<'0'||ch>'9') 17 { 18 if(ch=='-') 19 f=-1; 20 ch=getchar(); 21 } 22 while(ch>='0'&&ch<='9') 23 { 24 x=x*10+ch-'0'; 25 ch=getchar(); 26 } 27 x*=f; 28 } 29 inline void update(int x) 30 { 31 size[x]=size[son[x][1]]+size[son[x][2]]+1; 32 if(x&&tag[x]) 33 { 34 tag[x]^=1; 35 swap(son[x][1],son[x][2]); 36 tag[son[x][1]]^=1,tag[son[x][2]]^=1; 37 } 38 } 39 inline int newnode(int x) 40 { 41 ++sum_p;size[sum_p]=1; 42 val[sum_p]=x;rnd[sum_p]=rand(); 43 tag[sum_p]=0; 44 return sum_p; 45 } 46 int merge(int x,int y) 47 { 48 if(x==0||y==0) return x+y; 49 update(x),update(y); 50 if(rnd[x]<rnd[y]) 51 { 52 son[x][2]=merge(son[x][2],y); 53 update(x); 54 return x; 55 } 56 else 57 { 58 son[y][1]=merge(x,son[y][1]); 59 update(y); 60 return y; 61 } 62 } 63 inline void split(int &x,int &y,int k,int pos) 64 { 65 if(!pos) 66 x=y=0; 67 else 68 { 69 update(pos); 70 if(k<=size[son[pos][1]]) 71 { 72 y=pos; 73 split(x,son[pos][1],k,son[pos][1]); 74 } 75 else 76 { 77 x=pos; 78 split(son[pos][2],y,k-size[son[pos][1]]-1,son[pos][2]); 79 } 80 update(pos); 81 } 82 } 83 void rev(int l,int r) 84 { 85 int a,b,c,d; 86 split(a,b,r+1,root); 87 split(c,d,l,a); 88 tag[d]=1; 89 root=merge(merge(c,d),b); 90 } 91 void print(int x) 92 { 93 if(!x) return; 94 update(x); 95 print(son[x][1]); 96 if (val[x]>=1&&val[x]<=n) printf("%d ",val[x]); 97 print(son[x][2]); 98 } 99 int main() 100 { 101 srand((unsigned)time(NULL)); 102 scanf("%d%d",&n,&m); 103 root=build(1,n+2); 104 for(register int i=1;i<=m;i++) 105 { 106 register int l,r; 107 scanf("%d%d",&l,&r); 108 rev(l,r); 109 } 110 print(root); 111 }