平衡树学习总结、LCT练习题
Splay:
像BST(二叉搜索树)一样插入查询,可以改变树的形状,可以区间翻转,可以实现动态树,不可持久化。
核心代码:
1 void rotate(int a) // 旋转 2 { 3 int b = fa[a], c = fa[b]; 4 int k = son[b][1] == a, w = son[a][!k]; 5 6 if (no_root(b)) son[c][son[c][1] == b] = a; 7 son[a][!k] = b; 8 son[b][k] = w; 9 10 if (w) fa[w] = b; 11 fa[b] = a; 12 fa[a] = c; 13 pushup(b); 14 } 15 16 void splay(int x) // 将x移动到splay的根 17 { 18 int y = x, z = 0; 19 stk[++z] = y; 20 21 while (no_root(y)) stk[++z] = y = fa[y]; 22 while (z) pushdown(stk[z--]); 23 24 while (no_root(x)) 25 { 26 y = fa[x]; z = fa[y]; 27 if (no_root(y)) rotate((son[y][0] == x) ^ (son[z][0] == y) ? x : y); 28 rotate(x); 29 } 30 pushup(x); 31 }
Treap:
具有堆性质的BST,每个点有两个关键字,一个key为原来BST维护的值,一个fix
值,一个节点新建时,给予它一个随机的fix值,以fix为关键字构成最小根,Treap的期望高度为O(log n)。
【模板】普通平衡树(题目):
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 7 const int N = 2000010, INF = 1e9 + 7; 8 9 int root; 10 11 struct Node 12 { 13 int l, r, val, size, dat, cnt; 14 Node() {} 15 Node(int l, int r, int val, int size, int cnt) :l(l), r(r), val(val), size(size), cnt(cnt) {} 16 }; 17 18 int cnt; 19 Node tr[N]; 20 21 int New(int x) 22 { 23 tr[++cnt] = Node(0, 0, x, 1, 1); 24 tr[cnt].dat = rand(); 25 return cnt; 26 } 27 28 void update(int q) 29 { 30 tr[q].size = tr[tr[q].l].size + tr[q].cnt + tr[tr[q].r].size; 31 } 32 33 void build() 34 { 35 New(-INF), New(INF); 36 root = 1; 37 tr[1].r = 2; 38 update(root); 39 } 40 41 void zig(int &q) // 右旋 42 { 43 int p = tr[q].l; 44 tr[q].l = tr[p].r; 45 tr[p].r = q; 46 q = p; 47 48 update(tr[q].r); 49 update(q); 50 } 51 52 void zag(int& q) 53 { 54 int p = tr[q].r; 55 tr[q].r = tr[p].l; 56 tr[p].l = q; 57 q = p; 58 59 update(tr[q].l); 60 update(q); 61 } 62 63 64 void insert(int& q, int x) 65 { 66 if (!q) 67 { 68 q = New(x); 69 return; 70 } 71 72 if (x == tr[q].val) 73 { 74 tr[q].cnt++; 75 update(q); 76 return; 77 } 78 79 if (x < tr[q].val) 80 { 81 insert(tr[q].l, x); 82 if (tr[q].dat < tr[tr[q].l].dat) zig(q); 83 } 84 else 85 { 86 insert(tr[q].r, x); 87 if (tr[q].dat < tr[tr[q].r].dat) zag(q); 88 } 89 update(q); 90 } 91 92 void Delete(int &q, int x) 93 { 94 if (!q) return; 95 if (x == tr[q].val) 96 { 97 if (tr[q].cnt > 1) 98 { 99 tr[q].cnt--; 100 update(q); 101 return; 102 } 103 if (tr[q].l || tr[q].r) 104 { 105 if (tr[q].r == 0 || tr[tr[q].l].dat > tr[tr[q].r].dat) zig(q), Delete(tr[q].r, x); 106 else zag(q), Delete(tr[q].l, x); 107 update(q); 108 } 109 else q = 0; 110 return; 111 } 112 113 if (x < tr[q].val) Delete(tr[q].l, x); 114 else Delete(tr[q].r, x); 115 update(q); 116 } 117 118 int find_rank(int q, int x) 119 { 120 if (!q) return 0; 121 if (x == tr[q].val) return tr[tr[q].l].size + 1; 122 if (x < tr[q].val) return find_rank(tr[q].l, x); 123 else return find_rank(tr[q].r, x) + tr[q].cnt + tr[tr[q].l].size; 124 } 125 126 int find_num(int q, int x) 127 { 128 if (!q) return INF; 129 if (x <= tr[tr[q].l].size) return find_num(tr[q].l, x); 130 if (x <= tr[tr[q].l].size + tr[q].cnt) return tr[q].val; 131 return find_num(tr[q].r, x - tr[tr[q].l].size - tr[q].cnt); 132 } 133 134 int find_befor(int x) 135 { 136 int ans = 1, q = root; 137 while (q) 138 { 139 if (x == tr[q].val) 140 { 141 if (tr[q].l > 0) 142 { 143 q = tr[q].l; 144 while (tr[q].r > 0) q = tr[q].r; 145 ans = q; 146 } 147 break; 148 } 149 if (tr[q].val<x && tr[q].val>tr[ans].val) ans = q; 150 if (x < tr[q].val) q = tr[q].l; 151 else q = tr[q].r; 152 } 153 return tr[ans].val; 154 } 155 156 int find_nex(int x) 157 { 158 int ans = 2, q = root; 159 while (q) 160 { 161 if (x == tr[q].val) 162 { 163 if (tr[q].r > 0) 164 { 165 q = tr[q].r; 166 while (tr[q].l > 0) q = tr[q].l; 167 ans = q; 168 } 169 break; 170 } 171 if (tr[q].val>x && tr[q].val<tr[ans].val) ans = q; 172 if (x < tr[q].val) q = tr[q].l; 173 else q = tr[q].r; 174 } 175 return tr[ans].val; 176 } 177 178 int main() 179 { 180 build(); 181 182 int q; 183 scanf("%d", &q); 184 while (q--) 185 { 186 int op, x; 187 scanf("%d%d", &op, &x); 188 switch (op) 189 { 190 case 1: 191 { 192 insert(root, x); 193 break; 194 } 195 case 2: 196 { 197 Delete(root, x); 198 break; 199 } 200 case 3: 201 { 202 printf("%d\n", find_rank(root, x) - 1); 203 break; 204 } 205 case 4: 206 { 207 printf("%d\n", find_num(root, x + 1)); 208 break; 209 } 210 case 5: 211 { 212 printf("%d\n", find_befor(x)); 213 break; 214 } 215 216 case 6: 217 { 218 printf("%d\n", find_nex(x)); 219 break; 220 } 221 } 222 } 223 }
【模板】文艺平衡树(题目):
1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 #include<iostream> 5 #include<algorithm> 6 using namespace std; 7 8 const int N = 2000010; 9 10 int n; 11 int w[N]; 12 int lazy[N]; 13 int root; 14 15 vector<int> ans; 16 17 struct Node 18 { 19 int son[2], fa, val, size; 20 Node() {} 21 }; 22 23 Node tr[N]; 24 25 void update(int q) 26 { 27 tr[q].size = tr[tr[q].son[0]].size + tr[tr[q].son[1]].size + 1; 28 } 29 30 int build(int l, int r, int f) 31 { 32 int q = (l + r) >> 1; 33 tr[q].fa = f; 34 tr[q].val = w[q]; 35 36 if (l < q) tr[q].son[0] = build(l, q - 1, q); 37 if (r > q) tr[q].son[1] = build(q + 1, r, q); 38 update(q); 39 return q; 40 } 41 42 void pushdown(int x) 43 { 44 if (!lazy[x]) return; 45 46 lazy[tr[x].son[0]] ^= 1; 47 lazy[tr[x].son[1]] ^= 1; 48 swap(tr[x].son[0], tr[x].son[1]); 49 lazy[x] = 0; 50 } 51 52 int find1(int x) 53 { 54 int q = root; 55 while (true) 56 { 57 pushdown(q); 58 if (tr[q].son[0] && tr[tr[q].son[0]].size >= x) q = tr[q].son[0]; 59 else 60 { 61 int rank = (tr[q].son[0] ? tr[tr[q].son[0]].size : 0) + 1; 62 if (x <= rank) return q; 63 x -= rank; 64 q = tr[q].son[1]; 65 } 66 } 67 } 68 69 void rotate(int x) 70 { 71 int y = tr[x].fa, z = tr[y].fa, k = tr[y].son[1] == x, w = tr[x].son[!k]; 72 73 if (z) tr[z].son[tr[z].son[1] == y] = x; 74 else root = x; 75 tr[y].son[k] = w; 76 tr[x].son[!k] = y; 77 78 if (w) tr[w].fa = y; 79 tr[x].fa = z; 80 tr[y].fa = x; 81 update(y); 82 update(x); 83 } 84 85 void splay(int x, int f) 86 { 87 while (tr[x].fa != f) 88 { 89 int y = tr[x].fa, z = tr[y].fa; 90 if (z != f) rotate(((tr[y].son[1] == x) ^ (tr[z].son[1] == y)) ? x : y); 91 rotate(x); 92 } 93 } 94 95 void print(int x) 96 { 97 pushdown(x); 98 if (tr[x].son[0]) print(tr[x].son[0]); 99 ans.push_back(tr[x].val); 100 if (tr[x].son[1]) print(tr[x].son[1]); 101 } 102 103 int main() 104 { 105 int q; 106 scanf("%d%d", &n,&q); 107 108 for (int i = 1; i <= n + 2; i++) w[i] = i - 1; 109 110 root = build(1, n + 2, 0); 111 112 while (q--) 113 { 114 int l, r; 115 scanf("%d%d", &l, &r); 116 l = find1(l), r = find1(r + 2); 117 splay(l, 0), splay(r, l); 118 lazy[tr[tr[root].son[1]].son[0]] ^= 1; 119 } 120 121 print(root); 122 for (int i = 0; i < n; i++) printf("%d ", ans[i + 1]); 123 }
【模板】二逼平衡树(题目):
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 7 const int N = 2000010, INF = 2147483647; 8 9 int n; 10 int a[N]; 11 12 struct Treap 13 { 14 struct Node 15 { 16 int l, r, val, size, dat, cnt; 17 Node() {} 18 Node(int l, int r, int val, int size, int cnt) :l(l), r(r), val(val), size(size), cnt(cnt) {} 19 }; 20 21 int cnt; 22 Node tr[N]; 23 24 int New(int x) 25 { 26 tr[++cnt] = Node(0, 0, x, 1, 1); 27 tr[cnt].dat = rand(); 28 return cnt; 29 } 30 31 void update(int q) 32 { 33 tr[q].size = tr[tr[q].l].size + tr[q].cnt + tr[tr[q].r].size; 34 } 35 36 void zig(int& q) // 右旋 37 { 38 int p = tr[q].l; 39 tr[q].l = tr[p].r; 40 tr[p].r = q; 41 q = p; 42 43 update(tr[q].r); 44 update(q); 45 } 46 47 void zag(int& q) 48 { 49 int p = tr[q].r; 50 tr[q].r = tr[p].l; 51 tr[p].l = q; 52 q = p; 53 54 update(tr[q].l); 55 update(q); 56 } 57 58 void insert(int& q, int x) 59 { 60 if (!q) 61 { 62 q = New(x); 63 update(q); 64 return; 65 } 66 67 if (x == tr[q].val) 68 { 69 tr[q].cnt++; 70 update(q); 71 return; 72 } 73 74 if (x < tr[q].val) 75 { 76 insert(tr[q].l, x); 77 if (tr[q].dat < tr[tr[q].l].dat) zig(q); 78 } 79 else 80 { 81 insert(tr[q].r, x); 82 if (tr[q].dat < tr[tr[q].r].dat) zag(q); 83 } 84 update(q); 85 } 86 87 void Delete(int& q, int x) 88 { 89 if (!q) return; 90 if (x == tr[q].val) 91 { 92 if (tr[q].cnt > 1) 93 { 94 tr[q].cnt--; 95 update(q); 96 return; 97 } 98 if (tr[q].l || tr[q].r) 99 { 100 if (tr[q].r == 0 || tr[tr[q].l].dat > tr[tr[q].r].dat) zig(q), Delete(tr[q].r, x); 101 else zag(q), Delete(tr[q].l, x); 102 update(q); 103 } 104 else q = 0; 105 return; 106 } 107 else if (x < tr[q].val) Delete(tr[q].l, x); 108 else Delete(tr[q].r, x); 109 110 if(q) update(q); 111 } 112 113 int find_rank(int q, int x) 114 { 115 if (!q) return 0; 116 if (x == tr[q].val) return tr[tr[q].l].size; 117 else if (x < tr[q].val) return find_rank(tr[q].l, x); 118 else return find_rank(tr[q].r, x) + tr[q].cnt + tr[tr[q].l].size; 119 } 120 121 int find_num(int q, int x) 122 { 123 if (!q) return INF; 124 if (x <= tr[tr[q].l].size) return find_num(tr[q].l, x); 125 else if (x <= tr[tr[q].l].size + 1) return tr[q].val; 126 return find_num(tr[q].r, x - tr[tr[q].l].size - tr[q].cnt); 127 } 128 129 int find_pre(int p, int k) 130 { 131 if (!p) return -INF; 132 if (tr[p].val >= k) return find_pre(tr[p].l, k); 133 else return max(tr[p].val, find_pre(tr[p].r, k)); 134 } 135 136 int find_next(int p, int k) 137 { 138 if (!p) return INF; 139 if (tr[p].val <= k) return find_next(tr[p].r, k); 140 else return min(tr[p].val, find_next(tr[p].l, k)); 141 } 142 }; 143 144 Treap treap; 145 146 struct SEG 147 { 148 int root[N]; 149 150 void build(int q, int l, int r) 151 { 152 for (int i = l; i <= r; i++) 153 { 154 treap.insert(root[q], a[i]); 155 } 156 157 if (l == r) return; 158 int mid = (l + r) >> 1; 159 build(q << 1, l, mid); 160 build(q << 1 | 1, mid + 1, r); 161 } 162 163 int find_rank(int q, int l, int r, int L, int R, int x) 164 { 165 if (L > r || R < l) return 0; 166 if (L <= l && r <= R) return treap.find_rank(root[q], x); 167 168 int mid = (l + r) >> 1; 169 return find_rank(q << 1, l, mid, L, R, x) + find_rank(q << 1 | 1, mid + 1, r, L, R, x); 170 } 171 172 int find_num(int L, int R, int k) 173 { 174 int l = 0, r = 1e8; 175 while (l < r) 176 { 177 int mid = (l + r + 1) >> 1; 178 if (find_rank(1, 1, n, L, R, mid) < k) l = mid; 179 else r = mid - 1; 180 } 181 return r; 182 } 183 184 void modify(int q, int l, int r, int x, int k) 185 { 186 treap.Delete(root[q], a[x]); 187 treap.insert(root[q], k); 188 189 if (l == r) return; 190 191 int mid = (l + r) >> 1; 192 if (x <= mid) modify(q << 1, l, mid, x, k); 193 else modify(q << 1 | 1, mid + 1, r, x, k); 194 } 195 196 int find_pre(int q, int l, int r, int L, int R, int x) 197 { 198 if (L > r || l > R) return -INF; 199 int mid = (l + r) >> 1; 200 if (L <= l && r <= R) return treap.find_pre(root[q], x); 201 else return max(find_pre(q << 1, l, mid, L, R, x), find_pre(q << 1 | 1, mid + 1, r, L, R, x)); 202 } 203 204 int find_next(int q, int l, int r, int L, int R, int x) 205 { 206 if (L > r || l > R) return INF; 207 int mid = (l + r) >> 1; 208 if (L <= l && r <= R) return treap.find_next(root[q], x); 209 else return min(find_next(q << 1, l, mid, L, R, x), find_next(q << 1 | 1, mid + 1, r, L, R, x)); 210 } 211 }; 212 213 SEG seg; 214 215 int main() 216 { 217 int m; 218 scanf("%d%d", &n, &m); 219 for (int i = 1; i <= n; i++) scanf("%d", &a[i]); 220 221 seg.build(1, 1, n); 222 223 while (m--) 224 { 225 int op; 226 scanf("%d", &op); 227 if (op == 1) 228 { 229 int l, r, k; 230 scanf("%d%d%d", &l, &r, &k); 231 printf("%d\n", seg.find_rank(1, 1, n, l, r, k) + 1); 232 } 233 if (op == 2) 234 { 235 int l, r, k; 236 scanf("%d%d%d", &l, &r, &k); 237 printf("%d\n", seg.find_num(l, r, k)); 238 } 239 if (op == 3) 240 { 241 int pos, k; 242 scanf("%d%d", &pos, &k); 243 seg.modify(1, 1, n, pos, k); 244 a[pos] = k; 245 } 246 if (op == 4) 247 { 248 int l, r, k; 249 scanf("%d%d%d", &l, &r, &k); 250 printf("%d\n", seg.find_pre(1, 1, n, l, r, k)); 251 } 252 if (op == 5) 253 { 254 int l, r, k; 255 scanf("%d%d%d", &l, &r, &k); 256 printf("%d\n", seg.find_next(1, 1, n, l, r, k)); 257 } 258 } 259 }
这题目就离谱
【BZOJ1251】序列终结者(题目):
类似于线段树一样传翻转标记与相加标记
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 7 const int N = 200010; 8 9 int n, m; 10 int root, cnt; 11 int num[N]; 12 int fa[N], son[N][2]; 13 int size1[N], v[N], mx[N]; 14 int add[N], rev[N]; 15 16 void pushup(int q) 17 { 18 size1[q] = size1[son[q][0]] + size1[son[q][1]] + 1; 19 mx[q] = max(v[q], max(mx[son[q][0]], mx[son[q][1]])); 20 } 21 22 void pushdown(int q) 23 { 24 if (rev[q]) 25 { 26 swap(son[q][0], son[q][1]); 27 rev[son[q][0]] ^= 1; 28 rev[son[q][1]] ^= 1; 29 rev[q] = 0; 30 } 31 32 if (add[q]) 33 { 34 if (son[q][0]) add[son[q][0]] += add[q], v[son[q][0]] += add[q], mx[son[q][0]] += add[q]; 35 if (son[q][1]) add[son[q][1]] += add[q], v[son[q][1]] += add[q], mx[son[q][1]] += add[q]; 36 add[q] = 0; 37 } 38 } 39 40 int build(int l, int r, int pa) 41 { 42 if (l > r) return 0; 43 int q = ++cnt; 44 int mid = (l + r) >> 1; 45 46 fa[q] = pa; 47 v[q] = mx[q] = num[mid]; 48 son[q][0] = build(l, mid - 1, q); 49 son[q][1] = build(mid + 1, r, q); 50 pushup(q); 51 return q; 52 } 53 54 int find(int x) 55 { 56 int q = root; 57 while (q) 58 { 59 pushdown(q); 60 if (x <= size1[son[q][0]]) q = son[q][0]; 61 else 62 { 63 x -= size1[son[q][0]] + 1; 64 if (!x) return q; 65 q = son[q][1]; 66 } 67 } 68 return 0; 69 } 70 71 void rotate(int x) 72 { 73 int y = fa[x], z = fa[y], k = son[y][1] == x, w = son[x][!k]; 74 75 pushdown(x); 76 pushdown(y); 77 78 if (z) son[z][son[z][1] == y] = x; 79 son[y][k] = w; 80 son[x][!k] = y; 81 82 if (w) fa[w] = y; 83 fa[y] = x; 84 fa[x] = z; 85 86 pushup(x); 87 pushup(y); 88 } 89 90 void splay(int x, int pa) 91 { 92 while (fa[x] != pa) 93 { 94 int y = fa[x], z = fa[y]; 95 if (z != pa) rotate((son[y][1] == x) ^ (son[z][1] == y) ? x : y); 96 rotate(x); 97 } 98 if (!pa) root = x; 99 } 100 101 void split(int l, int r) 102 { 103 l = find(l), r = find(r + 2); 104 splay(l, 0), splay(r, l); 105 } 106 107 int main() 108 { 109 scanf("%d%d", &n, &m); 110 111 mx[0] = num[1] = num[n + 2] = -2e9; 112 root = build(1, n + 2, 0); 113 114 while (m--) 115 { 116 int k, l, r, s; 117 scanf("%d%d%d", &k, &l, &r); 118 split(l, r); 119 if (k == 1) 120 { 121 scanf("%d", &s); 122 add[son[son[root][1]][0]] += s; 123 v[son[son[root][1]][0]] += s; 124 mx[son[son[root][1]][0]] += s; 125 } 126 else if (k == 2) rev[son[son[root][1]][0]] ^= 1; 127 else if (k == 3) printf("%d\n", mx[son[son[root][1]][0]]); 128 } 129 }
【BZOJ3262】陌上花开(题目):
三维偏序模板,树状数组套平衡树,以b为关键字建树状数组,每个树状数组节点以c为关键字建平衡树,以a为关键字从小到大枚举进行插入操作(a一样大的要同时插入),在树状数组中插入b,每次插入再在当前节点的平衡树中插入c。
完成当前a的插入操作后立即进行询问,这样能保证已经插入的所有元素的a都小于等于当期元素,询问时查询树状数组中小于b的节点所代表的平衡树中小于c的节点一共有多少,得出的便是答案。
这不是CDQ模板么
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 7 const int N = 2000010; 8 9 int n, k; 10 11 struct SPLAY 12 { 13 struct tree 14 { 15 int val, fa, cnt, size, son[2]; 16 tree() {} 17 tree(int val, int fa, int cnt, int size) :val(val), fa(fa), cnt(cnt), size(size) {} 18 }; 19 20 int cnt = 0; 21 tree tr[N]; 22 23 int New(int c) 24 { 25 cnt++; 26 tr[cnt] = tree(c, 0, 1, 1); 27 tr[cnt].son[0] = tr[cnt].son[1] = 0; 28 return cnt; 29 } 30 31 void pushup(int q) 32 { 33 tr[q].size = tr[q].cnt; 34 int ls = tr[q].son[0], rs = tr[q].son[1]; 35 if (ls) tr[q].size += tr[ls].size; 36 if (rs) tr[q].size += tr[rs].size; 37 } 38 39 void rotate(int x) 40 { 41 int y = tr[x].fa, z = tr[y].fa, d = tr[y].son[1] == x, w = tr[x].son[!d]; 42 43 if (z) tr[z].son[tr[z].son[1] == y] = x; 44 tr[y].son[d] = w; 45 tr[x].son[!d] = y; 46 47 if (w) tr[w].fa = y; 48 tr[y].fa = x; 49 tr[x].fa = z; 50 51 pushup(y); 52 pushup(x); 53 } 54 55 void splay(int x, int &rt) 56 { 57 if (x == rt) return; 58 int pa = tr[rt].fa; 59 while (tr[x].fa != pa) 60 { 61 int y = tr[x].fa, z = tr[y].fa; 62 if (tr[y].fa != pa) rotate((tr[y].son[1] == x) ^ (tr[z].son[1] == y) ? x : y); 63 rotate(x); 64 } 65 rt = x; 66 } 67 68 void insert(int& rt, int c) 69 { 70 if (!rt) 71 { 72 rt = New(c); 73 return; 74 } 75 76 int q = rt; 77 while (true) 78 { 79 tr[q].size++; 80 if (tr[q].val == c) 81 { 82 tr[q].cnt++; 83 return; 84 } 85 int d = c > tr[q].val; 86 if (tr[q].son[d]) q = tr[q].son[d]; 87 else 88 { 89 tr[q].son[d] = New(c); 90 tr[tr[q].son[d]].fa = q; 91 splay(tr[q].son[d], rt); 92 return; 93 } 94 } 95 } 96 97 int query(int q, int c) 98 { 99 if (!q) return 0; 100 if (tr[q].val == c) return (tr[q].son[0] ? tr[tr[q].son[0]].size : 0) + tr[q].cnt; 101 else if (tr[q].val > c) return query(tr[q].son[0], c); 102 else return (tr[q].son[0] ? tr[tr[q].son[0]].size : 0) + tr[q].cnt + query(tr[q].son[1], c); 103 } 104 }; 105 SPLAY Splay; 106 107 struct TREE 108 { 109 int root[N]; 110 111 int lowbit(int x) 112 { 113 return x & -x; 114 } 115 116 void insert(int x, int y) 117 { 118 for (; x <= k; x += lowbit(x)) 119 { 120 Splay.insert(root[x], y); 121 } 122 } 123 124 int query(int x, int y) 125 { 126 int res = 0; 127 for (; x; x -= lowbit(x)) 128 { 129 res += Splay.query(root[x], y); 130 } 131 return res; 132 } 133 }; 134 TREE Tree; 135 136 struct Node 137 { 138 int a, b, c; 139 Node() {} 140 }; 141 142 Node fl[N]; 143 144 bool cmp(Node a, Node b) 145 { 146 return a.a < b.a; 147 } 148 149 int f[N], g[N]; 150 bool st[N]; 151 152 int main() 153 { 154 scanf("%d%d", &n, &k); 155 for (int i = 1; i <= n; i++) 156 { 157 scanf("%d%d%d", &fl[i].a, &fl[i].b, &fl[i].c); 158 } 159 160 sort(fl + 1, fl + 1 + n, cmp); 161 162 for (int i = 1; i <= n; i++) 163 { 164 if (!st[i]) 165 { 166 for (int j = i; fl[j].a == fl[i].a && j <= n; j++) 167 { 168 Tree.insert(fl[j].b, fl[j].c); 169 st[j] = true; 170 } 171 } 172 f[i] = Tree.query(fl[i].b, fl[i].c); 173 } 174 175 for (int i = 1; i <= n; i++) g[f[i]]++; 176 for (int i = 1; i <= n; i++) printf("%d\n", g[i]); 177 }
【HNOI2012】永无乡(题目):
并查集维护联通,Splay启发式合并(暴力合并)。
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 7 #define MAX 500000 8 9 struct Node 10 { 11 int ch[2]; 12 int val, ff, size; 13 }t[MAX]; 14 15 int f[MAX]; 16 int root[MAX], tot; 17 int hh[MAX]; 18 int N, M; 19 20 int getf(int x) 21 { 22 return x == f[x] ? x : f[x] = getf(f[x]); 23 } 24 25 inline void pushup(int x) 26 { 27 t[x].size = t[t[x].ch[0]].size + t[t[x].ch[1]].size + 1; 28 } 29 30 inline void rotate(int x) 31 { 32 int y = t[x].ff; 33 int z = t[y].ff; 34 int k = t[y].ch[1] == x; 35 t[z].ch[t[z].ch[1] == y] = x; t[x].ff = z; 36 t[y].ch[k] = t[x].ch[k ^ 1]; t[t[x].ch[k ^ 1]].ff = y; 37 t[x].ch[k ^ 1] = y; t[y].ff = x; 38 pushup(y); pushup(x); 39 } 40 41 inline void splay(int x, int goal) 42 { 43 while (t[x].ff != goal) 44 { 45 int y = t[x].ff, z = t[y].ff; 46 if (z != goal) 47 (t[z].ch[0] == y) ^ (t[y].ch[0] == x) ? rotate(x) : rotate(y); 48 rotate(x); 49 } 50 if (goal <= N)root[goal] = x; 51 } 52 53 inline void insert(int x, int bh) 54 { 55 int u = root[bh], ff = bh; 56 while (u && t[u].val != x) 57 ff = u, u = t[u].ch[x > t[u].val]; 58 u = ++tot; 59 t[u].size = 1; 60 t[u].ff = ff; 61 if (ff > N) 62 t[ff].ch[x > t[ff].val] = u; 63 t[u].val = x; t[u].ch[0] = t[u].ch[1] = 0; 64 splay(u, bh); 65 } 66 67 void DFS(int u, int kk) 68 { 69 if (t[u].ch[0])DFS(t[u].ch[0], kk); 70 if (t[u].ch[1])DFS(t[u].ch[1], kk); 71 insert(t[u].val, kk); 72 } 73 74 inline void Merge(int a, int b) 75 { 76 int x = getf(a), y = getf(b); 77 if (x == y)return; 78 if (t[root[x]].size > t[root[y]].size)swap(x, y); 79 f[x] = y; 80 DFS(root[x], y); 81 } 82 83 int kth(int bh, int k) 84 { 85 int u = root[bh]; 86 if (t[u].size < k)return -1; 87 while (233) 88 { 89 if (t[t[u].ch[0]].size + 1 < k) 90 { 91 k -= t[t[u].ch[0]].size + 1; 92 u = t[u].ch[1]; 93 } 94 else 95 if (t[t[u].ch[0]].size >= k) 96 u = t[u].ch[0]; 97 else 98 return t[u].val; 99 } 100 } 101 102 int main() 103 { 104 scanf("%d%d", &N, &M); 105 for (int i = 1; i <= N; ++i)root[i] = i + N, f[i] = i; 106 tot = N + N; 107 for (int i = 1; i <= N; ++i) 108 { 109 int x; 110 scanf("%d", &x); 111 hh[x] = i; 112 t[i + N].val = x; t[i + N].size = 1; t[i + N].ff = i; 113 } 114 for (int i = 1; i <= M; ++i) 115 { 116 int x, y; 117 scanf("%d%d", &x, &y); 118 Merge(x, y); 119 } 120 int Q; 121 scanf("%d", &Q); 122 while (Q--) 123 { 124 char ch[3]; int a, b; 125 scanf("%s%d%d", ch, &a, &b); 126 if (ch[0] == 'B') 127 { 128 Merge(a, b); 129 } 130 else 131 { 132 int ans = kth(getf(a), b); 133 printf("%d\n", ans == -1 ? ans : hh[ans]); 134 } 135 } 136 return 0; 137 }
【CF414E】Mashmokh's Designed Problem(题目)
不会
【BZOJ3600】没有人的算术(题目)
用一个实数来代表pair值,SGT来插入,线段树查询,具体看代码
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 7 typedef long long LL; 8 9 LL read() 10 { 11 LL x = 0, f = 0; 12 char ch = getchar(); 13 while (!isdigit(ch)) f = ch == '-', ch = getchar(); 14 while (isdigit(ch)) x = x * 10 + ch - '0', ch = getchar(); 15 return f ? -x : x; 16 } 17 18 const int N = 500010; 19 20 int n, m; 21 int root, R, top; 22 int mx[N], pos[N], id[N]; 23 double a[N]; 24 char ch[5]; 25 26 struct Node 27 { 28 int l, r; 29 Node() {} 30 Node(int l, int r) :l(l), r(r) {} 31 32 friend bool operator > (Node x, Node y) 33 { 34 if (a[x.l] > a[y.l])return 1; 35 if (a[x.l] == a[y.l] && a[x.r] > a[y.r])return 1; 36 return 0; 37 } 38 39 friend bool operator == (Node x, Node y) 40 { 41 if (x.l != y.l || x.r != y.r)return 0; 42 return 1; 43 } 44 }; 45 46 struct SGTree 47 { 48 int cnt; 49 Node v[N]; 50 int siz[N], ls[N], rs[N]; 51 52 void dfs(int k) 53 { 54 if (!k)return; 55 dfs(ls[k]); 56 id[++top] = k; 57 dfs(rs[k]); 58 } 59 60 void pushup(int q) 61 { 62 siz[q] = siz[ls[q]] + siz[rs[q]] + 1; 63 } 64 65 void build(int& q, int l, int r, double L, double R) // 建树 66 { 67 if (l > r) 68 { 69 q = 0; 70 return; 71 } 72 73 double vmid = (L + R) / 2.0; 74 int mid = (l + r) / 2; 75 76 q = id[mid]; 77 a[q] = vmid; 78 build(ls[q], l, mid - 1, L, vmid); 79 build(rs[q], mid + 1, r, vmid, R); 80 pushup(q); 81 } 82 83 void rebuild(int& q, double l, double r) // 重构 84 { 85 top = 0; 86 dfs(q); 87 build(q, 1, top, l, r); 88 } 89 90 int insert(int& q, double l, double r, Node val) 91 { 92 double mv = (l + r) / 2.0; 93 if (!q) 94 { 95 q = ++cnt; 96 a[q] = mv; 97 v[q] = val; 98 siz[q] = 1; 99 return q; 100 } 101 102 int p; 103 if (val == v[q]) return q; 104 else 105 { 106 siz[q]++; 107 if (val > v[q]) p = insert(rs[q], mv, r, val); 108 else p = insert(ls[q], l, mv, val); 109 } 110 if (siz[q] * 0.75 > max(siz[ls[q]], siz[rs[q]])) 111 { 112 if (R) 113 { 114 if (ls[q] == R) rebuild(ls[q], l, mv); 115 else rebuild(rs[q], mv, r); 116 R = 0; 117 } 118 } 119 else R = q; 120 return p; 121 } 122 }SGT; 123 124 void modify(int k, int l, int r, int v) 125 { 126 if (l == r) 127 { 128 mx[k] = l; 129 return; 130 } 131 132 int mid = (l + r) >> 1; 133 if (v <= mid) modify(k << 1, l, mid, v); 134 else modify(k << 1 | 1, mid + 1, r, v); 135 136 int x = mx[k << 1], y = mx[k << 1 | 1]; 137 if (a[pos[x]] >= a[pos[y]]) mx[k] = x; 138 else mx[k] = y; 139 } 140 141 int query(int k, int l, int r, int x, int y) 142 { 143 if (l == x && y == r) return mx[k]; 144 int t = 0, p = 0; 145 int mid = (l + r) >> 1; 146 if (x <= mid) 147 { 148 p = query(k << 1, l, mid, x, min(mid, y)); 149 if (a[pos[p]] > a[pos[t]])t = p; 150 } 151 if (y > mid) 152 { 153 p = query(k << 1 | 1, mid + 1, r, max(x, mid + 1), y); 154 if (a[pos[p]] > a[pos[t]])t = p; 155 } 156 return t; 157 } 158 159 int main() 160 { 161 n = read(), m = read(); 162 a[0] = -1; 163 SGT.insert(root, 0, 1, Node(0, 0)); 164 165 for (int i = 1; i <= n; i++) pos[i] = 1; 166 for (int i = 1; i <= n; i++) modify(1, 1, n, i); 167 168 for (int i = 1; i <= m; i++) 169 { 170 scanf("%s", ch + 1); 171 int l = read(), r = read(); 172 if (ch[1] == 'C') 173 { 174 int K = read(); 175 pos[K] = SGT.insert(root, 0, 1, Node(pos[l], pos[r])); 176 if (R) SGT.rebuild(root, 0, 1); R = 0; 177 modify(1, 1, n, K); 178 } 179 else printf("%d\n", query(1, 1, n, l, r)); 180 } 181 }
LCT:
【BZOJ2049】
模板
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 7 const int N = 10010; 8 const int inf = 1e9; 9 10 inline int read() 11 { 12 int x = 0, f = 1; char ch = getchar(); 13 while (ch < '0' || ch>'9') { if (ch == '-') f = -1; ch = getchar(); } 14 while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } 15 return x * f; 16 } 17 18 int n, m; 19 int fa[N], c[N][2], st[N]; 20 bool rev[N]; 21 22 inline bool isroot(int x) 23 { 24 return c[fa[x]][0] != x && c[fa[x]][1] != x; 25 } 26 27 void pushdown(int k) 28 { 29 int l = c[k][0], r = c[k][1]; 30 if (rev[k]) 31 { 32 rev[k] ^= 1; rev[l] ^= 1; rev[r] ^= 1; 33 swap(c[k][0], c[k][1]); 34 } 35 } 36 37 void rotate(int x) 38 { 39 int y = fa[x], z = fa[y], l, r; 40 if (c[y][0] == x)l = 0; else l = 1; r = l ^ 1; 41 if (!isroot(y)) 42 { 43 if (c[z][0] == y)c[z][0] = x; else c[z][1] = x; 44 } 45 fa[x] = z; fa[y] = x; fa[c[x][r]] = y; 46 c[y][l] = c[x][r]; c[x][r] = y; 47 } 48 49 void splay(int x) 50 { 51 int top = 0; st[++top] = x; 52 for (int i = x; !isroot(i); i = fa[i]) 53 { 54 st[++top] = fa[i]; 55 } 56 for (int i = top; i; i--)pushdown(st[i]); 57 while (!isroot(x)) 58 { 59 int y = fa[x], z = fa[y]; 60 if (!isroot(y)) 61 { 62 if (c[y][0] == x ^ c[z][0] == y)rotate(x); 63 else rotate(y); 64 } 65 rotate(x); 66 } 67 } 68 69 void access(int x) 70 { 71 int t = 0; 72 while (x) 73 { 74 splay(x); 75 c[x][1] = t; 76 t = x; x = fa[x]; 77 } 78 } 79 80 void rever(int x) 81 { 82 access(x); splay(x); rev[x] ^= 1; 83 } 84 85 void link(int x, int y) 86 { 87 rever(x); fa[x] = y; splay(x); 88 } 89 90 void cut(int x, int y) 91 { 92 rever(x); access(y); splay(y); c[y][0] = fa[x] = 0; 93 } 94 95 int find(int x) 96 { 97 access(x); splay(x); 98 int y = x; 99 while (c[y][0])y = c[y][0]; 100 return y; 101 } 102 103 int main() 104 { 105 char ch[10]; 106 int x, y; 107 n = read(); m = read(); 108 for (int i = 1; i <= m; i++) 109 { 110 scanf("%s", ch); 111 x = read(); y = read(); 112 if (ch[0] == 'C')link(x, y); 113 else if (ch[0] == 'D')cut(x, y); 114 else 115 { 116 if (find(x) == find(y))printf("Yes\n"); 117 else printf("No\n"); 118 } 119 } 120 return 0; 121 }
【BZOJ2631】
模板
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 7 typedef unsigned int UIT; 8 9 int read() 10 { 11 int x = 0, f = 1; char ch = getchar(); 12 while (ch < '0' || ch>'9') { if (ch == '-')f = -1; ch = getchar(); } 13 while (ch >= '0' && ch <= '9') { x = x * 10 + ch - '0'; ch = getchar(); } 14 return x * f; 15 } 16 17 const int N = 100010; 18 const int mod = 51061; 19 20 int n, m, top, cnt; 21 int c[N][2], fa[N]; 22 int siz[N], q[N]; 23 bool rev[N]; 24 UIT sum[N], val[N], at[N], mt[N]; 25 26 void cal(int x, int m, int a) 27 { 28 if (!x)return; 29 val[x] = (val[x] * m + a) % mod; 30 sum[x] = (sum[x] * m + a * siz[x]) % mod; 31 at[x] = (at[x] * m + a) % mod; 32 mt[x] = (mt[x] * m) % mod; 33 } 34 35 bool isroot(int x) 36 { 37 return c[fa[x]][0] != x && c[fa[x]][1] != x; 38 } 39 40 void update(int x) 41 { 42 int l = c[x][0], r = c[x][1]; 43 sum[x] = (sum[l] + sum[r] + val[x]) % mod; 44 siz[x] = (siz[l] + siz[r] + 1) % mod; 45 } 46 47 void pushdown(int x) 48 { 49 int l = c[x][0], r = c[x][1]; 50 if (rev[x]) 51 { 52 rev[x] ^= 1; rev[l] ^= 1; rev[r] ^= 1; 53 swap(c[x][0], c[x][1]); 54 } 55 int m = mt[x], a = at[x]; 56 mt[x] = 1; 57 at[x] = 0; 58 if (m != 1 || a != 0) 59 { 60 cal(l, m, a); cal(r, m, a); 61 } 62 } 63 64 void rotate(int x) 65 { 66 int y = fa[x], z = fa[y], l, r; 67 l = (c[y][1] == x); 68 r = l ^ 1; 69 70 if (!isroot(y)) c[z][c[z][1] == y] = x; 71 fa[x] = z; 72 fa[y] = x; 73 fa[c[x][r]] = y; 74 c[y][l] = c[x][r]; 75 c[x][r] = y; 76 77 update(y); 78 update(x); 79 } 80 81 void splay(int x) 82 { 83 q[++top] = x; 84 for (int i = x; !isroot(i); i = fa[i]) q[++top] = fa[i]; 85 86 while (top) pushdown(q[top--]); 87 while (!isroot(x)) 88 { 89 int y = fa[x], z = fa[y]; 90 if (!isroot(y)) 91 { 92 if (c[y][0] == x ^ c[z][0] == y) rotate(x); 93 else rotate(y); 94 } 95 rotate(x); 96 } 97 } 98 99 void access(int x) 100 { 101 for (int t = 0; x; t = x, x = fa[x]) 102 { 103 splay(x); 104 c[x][1] = t; 105 update(x); 106 } 107 } 108 109 void makeroot(int x) 110 { 111 access(x); 112 splay(x); 113 rev[x] ^= 1; 114 } 115 116 void split(int x, int y) 117 { 118 makeroot(y); 119 access(x); 120 splay(x); 121 } 122 123 void link(int x, int y) 124 { 125 makeroot(x); 126 fa[x] = y; 127 } 128 129 void cut(int x, int y) 130 { 131 makeroot(x); 132 access(y); 133 splay(y); 134 c[y][0] = fa[x] = 0; 135 } 136 137 int main() 138 { 139 n = read(); 140 m = read(); 141 142 for (int i = 1; i <= n; i++) val[i] = sum[i] = mt[i] = siz[i] = 1; 143 144 for (int i = 1; i < n; i++) 145 { 146 int u = read(), v = read(); 147 link(u, v); 148 } 149 150 char ch[5]; 151 while (m--) 152 { 153 scanf("%s", ch); 154 int u = read(), v = read(); 155 if (ch[0] == '+') 156 { 157 int x = read(); 158 split(u, v); cal(u, 1, x); 159 } 160 if (ch[0] == '-') 161 { 162 cut(u, v); 163 u = read(); v = read(); link(u, v); 164 } 165 if (ch[0] == '*') 166 { 167 int x = read(); 168 split(u, v); cal(u, x, 0); 169 } 170 if (ch[0] == '/') 171 { 172 split(u, v); 173 printf("%d\n", sum[u]); 174 } 175 } 176 }
【BZOJ4389】
模板
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 7 const int N = 200010; 8 9 typedef long long LL; 10 11 int n, m; 12 13 int f[N], son[N][2], tmp[N], c[N]; 14 bool rev[N]; 15 LL v[N], s[N], mx[N], tc[N], ta[N]; 16 LL st[N], sa[N], as[N]; 17 18 inline void read(int& a) 19 { 20 char c; 21 while (!(((c = getchar()) >= '0') && (c <= '9'))); 22 a = c - '0'; 23 while (((c = getchar()) >= '0') && (c <= '9'))(a *= 10) += c - '0'; 24 } 25 26 inline bool isroot(int x) 27 { 28 return !f[x] || son[f[x]][0] != x && son[f[x]][1] != x; 29 } 30 31 inline void rev1(int x) 32 { 33 if (!x)return; 34 swap(son[x][0], son[x][1]); 35 rev[x] ^= 1; 36 } 37 38 inline void col1(int x, LL y) 39 { 40 if (!x)return; 41 v[x] = mx[x] = tc[x] = y; 42 s[x] = y * c[x]; 43 ta[x] = 0; 44 sa[x] = s[x] + st[x]; 45 } 46 47 inline void add1(int x, LL y) 48 { 49 if (!x)return; 50 v[x] += y; 51 s[x] += y * c[x]; 52 mx[x] += y; 53 if (tc[x])tc[x] += y; else ta[x] += y; 54 sa[x] = s[x] + st[x]; 55 } 56 57 inline void pb(int x) 58 { 59 if (rev[x]) rev1(son[x][0]), rev1(son[x][1]), rev[x] = 0; 60 if (tc[x]) col1(son[x][0], tc[x]), col1(son[x][1], tc[x]), tc[x] = 0; 61 if (ta[x]) add1(son[x][0], ta[x]), add1(son[x][1], ta[x]), ta[x] = 0; 62 } 63 64 inline void up(int x) 65 { 66 s[x] = mx[x] = v[x]; c[x] = 1; 67 st[x] = as[x]; 68 for (int i = 0; i < 2; i++) 69 { 70 int y = son[x][i]; 71 if (y) { 72 c[x] += c[y]; 73 s[x] += s[y]; 74 mx[x] = max(mx[x], mx[y]); 75 st[x] += st[y]; 76 } 77 } 78 sa[x] = s[x] + st[x]; 79 } 80 81 inline void rotate(int x) 82 { 83 int y = f[x], w = son[y][1] == x; 84 son[y][w] = son[x][w ^ 1]; 85 if (son[x][w ^ 1]) f[son[x][w ^ 1]] = y; 86 if (f[y]) 87 { 88 int z = f[y]; 89 if (son[z][0] == y) son[z][0] = x; 90 else if (son[z][1] == y) son[z][1] = x; 91 } 92 f[x] = f[y]; 93 f[y] = x; 94 son[x][w ^ 1] = y; 95 up(y); 96 } 97 98 inline void splay(int x) 99 { 100 int s = 1, i = x, y; 101 tmp[1] = i; 102 while (!isroot(i)) tmp[++s] = i = f[i]; 103 while (s) pb(tmp[s--]); 104 while (!isroot(x)) 105 { 106 y = f[x]; 107 if (!isroot(y)) { if ((son[f[y]][0] == y) ^ (son[y][0] == x))rotate(x); else rotate(y); } 108 rotate(x); 109 } 110 up(x); 111 } 112 113 inline void access(int x) 114 { 115 for (int y = 0; x; y = x, x = f[x]) 116 { 117 splay(x); 118 if (son[x][1]) as[x] += sa[son[x][1]]; 119 if (son[x][1] = y) as[x] -= sa[y]; 120 up(x); 121 } 122 } 123 124 inline void makeroot(int x) 125 { 126 access(x); 127 splay(x); 128 rev1(x); 129 } 130 131 inline void link(int x, int y) 132 { 133 makeroot(x); 134 makeroot(y); 135 as[y] += sa[x]; 136 f[x] = y; 137 access(x); 138 } 139 140 inline void cutf(int x) 141 { 142 access(x); 143 splay(x); 144 f[son[x][0]] = 0; 145 son[x][0] = 0; 146 up(x); 147 } 148 149 inline void cut(int x, int y) 150 { 151 makeroot(x); 152 cutf(y); 153 } 154 155 inline void col(int x, int y, int z) 156 { 157 makeroot(x); 158 access(y); 159 splay(y); 160 col1(y, z); 161 } 162 163 inline void add(int x, int y, int z) 164 { 165 makeroot(x); 166 access(y); 167 splay(y); 168 add1(y, z); 169 } 170 171 inline LL chainsum(int x, int y) 172 { 173 makeroot(x); 174 access(y); 175 splay(y); 176 return s[y]; 177 } 178 179 inline LL chainmax(int x, int y) 180 { 181 makeroot(x); 182 access(y); 183 splay(y); 184 return mx[y]; 185 } 186 187 inline LL subtreesum(int x, int y) 188 { 189 makeroot(x); 190 access(y); 191 splay(y); 192 return as[y] + v[y]; 193 } 194 195 int main() 196 { 197 read(n); 198 for (int i = 1; i <= n; i++) 199 { 200 int x; 201 read(x); 202 v[i] = s[i] = mx[i] = sa[i] = x, c[i] = 1; 203 } 204 for (int i = 2; i <= n; i++) 205 { 206 int x; 207 read(x); 208 link(x, i); 209 } 210 read(m); 211 while (m--) 212 { 213 int op, x, y, z; 214 read(op), read(x), read(y); 215 if (op == 1) read(z), add(x, y, z); 216 if (op == 2) read(z), col(x, y, z); 217 if (op == 3) printf("%lld\n", subtreesum(x, y)); 218 if (op == 4) printf("%lld\n", chainmax(x, y)); 219 if (op == 5) printf("%lld\n", chainsum(x, y)); 220 if (op == 6) link(x, y); 221 if (op == 7) cut(x, y); 222 } 223 }
浙公网安备 33010602011771号