3223: Tyvj 1729 文艺平衡树
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 5918 Solved: 3535
[Submit][Status][Discuss]
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
【题解】
平衡树维护序列,大小顺序与节点内的权值无关,而是通过一开始钦定树的形态来钦定大小顺序
反转操作,把区间放到一颗子树内,显然子树根节点在区间中点,直接交换子树即可
1 /************************************************************** 2 Problem: 3223 3 User: 33511595 4 Language: C++ 5 Result: Accepted 6 Time:3040 ms 7 Memory:13012 kb 8 ****************************************************************/ 9 10 #include <iostream> 11 #include <cstdio> 12 #include <cstring> 13 #include <cstdlib> 14 #include <algorithm> 15 #include <queue> 16 #include <vector> 17 #include <map> 18 #include <string> 19 #include <cmath> 20 #define min(a, b) ((a) < (b) ? (a) : (b)) 21 #define max(a, b) ((a) > (b) ? (a) : (b)) 22 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a)) 23 template <class T> 24 inline void swap(T& a, T& b) 25 { 26 T tmp = a;a = b;b = tmp; 27 } 28 inline void read(int &x) 29 { 30 x = 0;char ch = getchar(), c = ch; 31 while(ch < ‘0‘ || ch > ‘9‘) c = ch, ch = getchar(); 32 while(ch <= ‘9‘ && ch >= ‘0‘) x = x * 10 + ch - ‘0‘, ch = getchar(); 33 if(c == ‘-‘) x = -x; 34 } 35 36 const int INF = 0x3f3f3f3f; 37 const int MAXN = 500000 + 10; 38 39 int ch[MAXN][2], fa[MAXN], size[MAXN], root,tag[MAXN], data[MAXN]; 40 int son(int x){return x == ch[fa[x]][1];} 41 void pushup(int rt) 42 { 43 size[rt] = size[ch[rt][1]] + size[ch[rt][0]] + 1; 44 } 45 void pushdown(int rt) 46 { 47 if(!tag[rt]) return; 48 int l = ch[rt][0], r = ch[rt][1]; 49 tag[l] ^= 1, tag[r] ^= 1; 50 swap(ch[l][0], ch[l][1]); 51 swap(ch[r][0], ch[r][1]); 52 tag[rt] = 0; 53 } 54 void rotate(int x) 55 { 56 int y = fa[x], z = fa[y], b = son(x), c = son(y), a = ch[x][!b]; 57 if(z) ch[z][c] = x; else root = x; fa[x] = z; 58 if(a) fa[a] = y; ch[y][b] = a; 59 ch[x][!b] = y, fa[y] = x; 60 pushup(y), pushup(x); 61 } 62 void splay(int x, int i) 63 { 64 while(fa[x] != i) 65 { 66 int y = fa[x], z = fa[y]; 67 if(z == i) rotate(x); 68 else 69 if(son(x) == son(y)) rotate(y), rotate(x); 70 else rotate(x), rotate(x); 71 } 72 } 73 int getkth(int rt, int x) 74 { 75 pushdown(rt);int l = ch[rt][0]; 76 if(size[l] + 1 == x) return rt; 77 else if(size[l] + 1 > x) return getkth(ch[rt][0], x); 78 else return getkth(ch[rt][1], x - size[l] - 1); 79 } 80 void turn(int l, int r) 81 { 82 l = getkth(root, l - 1), r = getkth(root, r + 1); 83 splay(l, 0);splay(r, l); 84 int now = ch[r][0]; 85 tag[now] ^= 1; 86 swap(ch[now][0], ch[now][1]); 87 pushdown(now); 88 } 89 int n, m, tmp1, tmp2; 90 void put(int x) 91 { 92 if(!x) return; 93 pushdown(x); 94 put(ch[x][0]); 95 if(x != 1 && x != n + 2)printf("%d ", data[x]); 96 put(ch[x][1]); 97 return; 98 } 99 int main() 100 { 101 read(n), read(m); 102 root = 1; 103 for(int i = 1;i <= n + 1;++ i) ch[i][1] = i + 1, fa[i + 1] = i, size[i] = n + 3 - i; 104 size[n + 2] = 1; 105 for(int i = 2;i <= n + 1;++ i) data[i] = i - 1; 106 for(int i = 1;i <= m;++ i) 107 { 108 read(tmp1), read(tmp2); 109 turn(tmp1 + 1, tmp2 + 1); 110 } 111 put(root); 112 return 0; 113 }