BZOJ 3223: Tyvj 1729 文艺平衡树
3223: Tyvj 1729 文艺平衡树
Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 3628 Solved: 2052
[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
小生的第三道伸展树板子题。初识Splay维护区间翻转操作。引用一位前辈的题解。、
splay的经典操作:翻转区间-->交换左右子树,注意打标记降低翻转次数。如何找到要操作的区间[l,r]:将当前排名(size)为l-1 +1 的节点转到根,将当前排名为r+2的节点转到根的右子树的根节点,则根的右子树的根节点的左子树为所求区间,直接打标记就可以了。
1 #include <bits/stdc++.h> 2 3 class Splay { 4 public: 5 Splay(void) { 6 root = NULL; 7 for (top = 0; top < siz; ++top) 8 stk[top] = tree + top; 9 } 10 11 inline void auto_build(int n) { 12 for (int i = 0; i <= n + 1; ++i) 13 insert(i); 14 } 15 16 inline void insert(int val) { 17 if (root == NULL) 18 root = newnode(val, NULL); 19 else { 20 node *t = root; 21 while (t->son[1] != NULL) 22 t = t->son[1]; 23 splay(t, NULL); 24 t->son[1] = newnode(val, t); 25 update(root); splay(t->son[1], NULL); 26 } 27 } 28 29 inline void reverse(int l, int r) { 30 ++l, ++r; 31 splay(rnk(l - 1), NULL); 32 splay(rnk(r + 1), root); 33 reverse(root->son[1]->son[0]); 34 } 35 36 inline void print(int n) { 37 for (int i = 1; i <= n; ++i) 38 printf("%d ", rnk(i + 1)->value); 39 } 40 private: 41 const static int siz = 1e5 + 5; 42 43 struct node { 44 int size; 45 int value; 46 bool reverse; 47 node *father; 48 node *son[2]; 49 }*root; 50 51 node tree[siz], *stk[siz]; int top; 52 53 inline node *newnode(int v, node *f) { 54 node *ret = stk[--top]; 55 ret->size = 1; 56 ret->value = v; 57 ret->father = f; 58 ret->son[0] = NULL; 59 ret->son[1] = NULL; 60 ret->reverse = false; 61 return ret; 62 } 63 64 inline void freenode(node *t) { 65 stk[top++] = t; 66 } 67 68 inline int size(node *t) { 69 return t == NULL ? 0 : t->size; 70 } 71 72 inline void update(node *t) { 73 t->size = 1; 74 t->size += size(t->son[0]); 75 t->size += size(t->son[1]); 76 } 77 78 inline bool son(node *f, node *s) { 79 if (f == NULL)return false; 80 return f->son[1] == s; 81 } 82 83 inline bool tag(node *t) { 84 return t == NULL ? false : t->reverse; 85 } 86 87 inline void reverse(node *t) { 88 if (t != NULL) 89 t->reverse ^= true; 90 } 91 92 inline void pushdown(node *t) { 93 if (tag(t)) { 94 std::swap(t->son[0], t->son[1]); 95 reverse(t->son[0]); 96 reverse(t->son[1]); 97 t->reverse ^= true; 98 } 99 } 100 101 inline void connect(node *f, node *s, bool k) { 102 if (f == NULL) 103 root = s; 104 else 105 f->son[k] = s; 106 if (s != NULL) 107 s->father = f; 108 } 109 110 inline void rotate(node *t) { 111 node *f = t->father; 112 node *g = f->father; 113 bool a = son(f, t), b = !a; 114 connect(f, t->son[b], a); 115 connect(g, t, son(g, f)); 116 connect(t, f, b); 117 update(f); 118 update(t); 119 } 120 121 inline void splay(node *t, node *p) {if (t) 122 while (t->father != p) { 123 node *f = t->father; 124 node *g = f->father; 125 pushdown(g); 126 pushdown(f); 127 pushdown(t); 128 if (g == p) 129 rotate(t); 130 else { 131 if (son(g, f) ^ son(f, t)) 132 rotate(t), rotate(t); 133 else 134 rotate(f), rotate(t); 135 } 136 } 137 } 138 139 inline node *find(int val) { 140 node *ret = root; 141 while (ret != NULL && ret->value != val) 142 pushdown(ret), ret = ret->son[val >= ret->value]; 143 return ret; 144 } 145 146 inline node *rnk(int kth) { 147 for (node *t = root; t; ) { 148 pushdown(t); 149 if (size(t->son[0]) < kth) { 150 kth -= size(t->son[0]); 151 if (kth == 1) 152 return t; 153 else 154 --kth, t = t->son[1]; 155 } 156 else 157 t = t->son[0]; 158 } 159 } 160 }S; 161 162 signed main(void) { 163 int n, m; scanf("%d%d", &n, &m); 164 S.auto_build(n); 165 for (int i = 1, l, r; i <= m; ++i) 166 scanf("%d%d", &l, &r), S.reverse(l, r); 167 S.print(n); 168 }
@Author: YouSiki