[BZOJ3223] [Tyvj1729] 文艺平衡树 (splay)
Posted CtrlCV
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[BZOJ3223] [Tyvj1729] 文艺平衡树 (splay)相关的知识,希望对你有一定的参考价值。
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
Source
Solution
splay的区间翻转。我的习惯是给序列两端加上虚拟节点,这样查询[l, r]时把l旋到根,把r+2旋到根的右儿子。
我建树时就建成一条链,因为之后的操作可以把它的深度逐渐变成均摊O(logn),所以开始的树的形态不影响复杂度。
1 #include <bits/stdc++.h> 2 using namespace std; 3 struct spaly 4 { 5 int siz, fa, c[2], rev; 6 }a[100005]; 7 int root, n; 8 9 void push_up(int k) 10 { 11 a[k].siz = a[a[k].c[0]].siz + a[a[k].c[1]].siz + 1; 12 } 13 14 void push_down(int k) 15 { 16 if(a[k].rev) 17 { 18 swap(a[k].c[0], a[k].c[1]), a[k].rev = 0; 19 a[a[k].c[0]].rev ^= 1, a[a[k].c[1]].rev ^= 1; 20 } 21 } 22 23 void rotate(int &k, int x) 24 { 25 int y = a[x].fa, z = a[y].fa; 26 int dy = a[y].c[1] == x, dz = a[z].c[1] == y; 27 push_down(y); 28 if(k == y) k = x, a[x].fa = z; 29 else a[z].c[dz] = x, a[x].fa = z; 30 a[y].c[dy] = a[x].c[dy ^ 1], a[a[x].c[dy ^ 1]].fa = y; 31 a[x].c[dy ^ 1] = y, a[y].fa = x; 32 push_up(y); 33 } 34 35 void splay(int &k, int x) 36 { 37 push_down(x); 38 while(k != x) 39 { 40 int y = a[x].fa, z = a[y].fa; 41 if(k != y) 42 if(a[y].c[1] == x ^ a[z].c[1] == y) rotate(k, x); 43 else rotate(k, y); 44 rotate(k, x); 45 } 46 push_up(x); 47 } 48 49 int find(int k, int x) 50 { 51 if(!k) return 0; 52 push_down(k); 53 if(x <= a[a[k].c[0]].siz) return find(a[k].c[0], x); 54 if(x == a[a[k].c[0]].siz + 1) return k; 55 return find(a[k].c[1], x - a[a[k].c[0]].siz - 1); 56 } 57 58 void printf(int k) 59 { 60 if(!k) return; 61 push_down(k), printf(a[k].c[0]); 62 if(k > 1 && k < n + 2) printf("%d ", k - 1); 63 printf(a[k].c[1]); 64 } 65 66 int main() 67 { 68 int m, l, r; 69 scanf("%d%d", &n, &m); 70 for(int i = 1; i <= n + 2; i++) 71 { 72 a[i].siz = n + 3 - i; 73 a[i].fa = i - 1, a[i].c[1] = i + 1; 74 } 75 a[n + 2].c[1] = 0, root = 1; 76 while(m--) 77 { 78 scanf("%d%d", &l, &r); 79 splay(root, find(root, l)); 80 splay(a[root].c[1], find(root, r + 2)); 81 a[a[a[root].c[1]].c[0]].rev ^= 1; 82 } 83 printf(root); 84 puts(""); 85 return 0; 86 }
以上是关于[BZOJ3223] [Tyvj1729] 文艺平衡树 (splay)的主要内容,如果未能解决你的问题,请参考以下文章