bzoj 1095 Hide 捉迷藏 - 动态点分治 -堆
Description
捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子。某天,Jiajia、Wind和孩子们决定在家里玩
捉迷藏游戏。他们的家很大且构造很奇特,由N个屋子和N-1条双向走廊组成,这N-1条走廊的分布使得任意两个屋
子都互相可达。游戏是这样进行的,孩子们负责躲藏,Jiajia负责找,而Wind负责操纵这N个屋子的灯。在起初的
时候,所有的灯都没有被打开。每一次,孩子们只会躲藏在没有开灯的房间中,但是为了增加刺激性,孩子们会要
求打开某个房间的电灯或者关闭某个房间的电灯。为了评估某一次游戏的复杂性,Jiajia希望知道可能的最远的两
个孩子的距离(即最远的两个关灯房间的距离)。 我们将以如下形式定义每一种操作: C(hange) i 改变第i个房
间的照明状态,若原来打开,则关闭;若原来关闭,则打开。 G(ame) 开始一次游戏,查询最远的两个关灯房间的
距离。
Input
第一行包含一个整数N,表示房间的个数,房间将被编号为1,2,3…N的整数。接下来N-1行每行两个整数a, b,
表示房间a与房间b之间有一条走廊相连。接下来一行包含一个整数Q,表示操作次数。接着Q行,每行一个操作,如
上文所示。
Output
对于每一个操作Game,输出一个非负整数到hide.out,表示最远的两个关灯房间的距离。若只有一个房间是关
着灯的,输出0;若所有房间的灯都开着,输出-1。
Sample Input
1 2
2 3
3 4
3 5
3 6
6 7
6 8
7
G
C 1
G
C 2
G
C 1
G
Sample Output
3
3
4
HINT
对于100%的数据, N ≤100000, M ≤500000。
题目大意
给定一棵树,每个点的颜色不是黑色就是白色,开始所有点的颜色都是黑色,要求支持两个操作:
- 翻转一个点的颜色
- 询问最远的黑点对的距离。如果只有1个黑点,那么输出0,如果没有黑点,输出-1。
由于有多次询问,所以不可能暴力求最长链。
如何快速处理最长链?于是想到了点分治。
现在的任务是让点分治支持修改操作。
因为最长距离不可加减,所以只能通过维护分治中心的各子树中,深度最大的点,然后取前两大更新答案。
因此,每个点维护两个堆,一个堆维护点分树上它的子树中深度最大的点的深度,一个堆维护在点分树上它的子树中所有点到它的父分治中心的距离。
除此之外,还要开一个全局堆维护答案。
对于修改操作,就是删除元素再插入元素,自己画画图就能想清楚(明明是yyf扯不清楚)。
问题是怎么让堆支持删除?再开个堆打标记就好了。
还有一个问题,如何求树上两点间的距离?两点的深度减去它们LCA的深度的两倍,求LCA用st表。
Code
1 /** 2 * bzoj 3 * Problem#1095 4 * Accepted 5 * Time: 13356ms 6 * Memory: 159584k 7 */ 8 #include <bits/stdc++.h> 9 using namespace std; 10 typedef bool boolean; 11 const signed int inf = (signed) (~0u >> 1) - 1; 12 13 typedef class Node { 14 public: 15 int val; 16 Node *l, *r; 17 18 Node(int val = 0, Node* l = NULL, Node* r = NULL):val(val), l(l), r(r) { } 19 }Node; 20 21 Node* merge(Node* a, Node* b) { 22 if(!a) return b; 23 if(!b) return a; 24 if(a->val < b->val) swap(a, b); 25 a->r = merge(a->r, b); 26 swap(a->l, a->r); 27 return a; 28 } 29 30 #define Limit 10000000 31 Node pool[Limit]; 32 Node *top = pool; 33 34 Node* newnode(int x) { 35 if(top >= pool + Limit) 36 return new Node(x, NULL, NULL); 37 top->val = x; 38 return top++; 39 } 40 41 #define clr(rt, dr) while(rt && dr && dr->val == rt->val) rt = merge(rt->l, rt->r), dr = merge(dr->l, dr->r) 42 typedef class Heap { 43 public: 44 int s; 45 Node* rt; 46 Node* dr; 47 48 Heap():s(0), rt(NULL), dr(NULL) { } 49 50 int top() { 51 if(!rt) return -1; 52 return rt->val; 53 } 54 55 int sectop() { 56 if(!rt) return -inf; 57 clr(rt->l, dr); 58 clr(rt->r, dr); 59 int lv = (rt->l) ? (rt->l->val) : (-inf), rv = (rt->r) ? (rt->r->val) : (-inf); 60 return (lv > rv) ? (lv) : (rv); 61 } 62 63 void pop() { 64 rt = merge(rt->l, rt->r); 65 clr(rt, dr); 66 } 67 68 void insert(int x) { 69 if(x < 0) return; 70 s++; 71 rt = merge(rt, newnode(x)); 72 clr(rt, dr); 73 } 74 75 void remove(int x) { 76 if(x < 0) return; 77 s--; 78 dr = merge(dr, newnode(x)); 79 clr(rt, dr); 80 } 81 82 int size() { 83 return s; 84 } 85 }Heap; 86 87 const int N = 1e5 + 5; 88 89 int n, m, n2; 90 vector<int> *g; 91 Heap *dtg, *dtf, gol; 92 int *siz, *fag, *dep, *erl; 93 int *Log2, *in; 94 boolean *vis, *ison; 95 96 inline void init() { 97 scanf("%d", &n), n2 = n << 1; 98 g = new vector<int>[(n + 1)]; 99 dtg = new Heap[(n + 1)]; 100 dtf = new Heap[(n + 1)]; 101 in = new int[(n + 1)]; 102 siz = new int[(n + 1)]; 103 fag = new int[(n + 1)]; 104 dep = new int[(n + 1)]; 105 erl = new int[(n2 + 1)]; 106 Log2 = new int[(n2 + 1)]; 107 vis = new boolean[(n + 1)]; 108 ison = new boolean[(n + 1)]; 109 fill(vis + 1, vis + n + 1, false); 110 fill(ison + 1, ison + n + 1, false); 111 for(int i = 1, u, v; i < n; i++) { 112 scanf("%d%d", &u, &v); 113 g[u].push_back(v); 114 g[v].push_back(u); 115 } 116 } 117 118 int cerl = 0; 119 void dfs1(int p, int fa) { 120 erl[++cerl] = p; 121 in[p] = cerl; 122 dep[p] = dep[fa] + 1; 123 for(int i = 0; i < (signed)g[p].size(); i++) { 124 int e = g[p][i]; 125 if(e == fa) continue; 126 dfs1(e, p); 127 erl[++cerl] = p; 128 } 129 } 130 131 #define bzmax 19 132 int st[19][N << 1]; 133 inline void init_st() { 134 Log2[1] = 0, dep[0] = 0; 135 for(int i = 2; i <= n2; i++) 136 Log2[i] = Log2[i >> 1] + 1; 137 dfs1(1, 0); 138 139 for(int i = 1; i < n2 - 1; i++) 140 st[0][i] = (dep[erl[i]] < dep[erl[i + 1]]) ? (erl[i]) : (erl[i + 1]); 141 for(int j = 1; j < bzmax; j++) 142 for(int i = 1, a, b; i + (1 << j) < n2; i++) { 143 a = st[j - 1][i], b = st[j - 1][i + (1 << (j - 1))]; 144 st[j][i] = (dep[a] < dep[b]) ? (a) : (b); 145 } 146 } 147 148 inline int Lca(int u, int v) { 149 int l = in[u], r = in[v], len, a, b; 150 if(l > r) swap(l, r); 151 len = Log2[r - l + 1]; 152 a = st[len][l], b = st[len][r - (1 << len) + 1]; 153 return (dep[a] < dep[b]) ? (a) : (b); 154 } 155 156 inline int dist(int u, int v) { 157 int lca = Lca(u, v); 158 return dep[u] + dep[v] - (dep[lca] << 1); 159 } 160 161 void dfs2(int p, int fa) { 162 siz[p] = 1; 163 for(int i = 0; i < (signed)g[p].size(); i++) { 164 int e = g[p][i]; 165 if(e == fa || vis[e]) continue; 166 dfs2(e, p); 167 siz[p] += siz[e]; 168 } 169 } 170 171 void dfs3(int p, int fa, int& cov, int& G, int& maxv) { 172 int cmp = cov - siz[p]; 173 for(int i = 0; i < (signed)g[p].size(); i++) { 174 int e = g[p][i]; 175 if(e == fa || vis[e]) continue; 176 dfs3(e, p, cov, G, maxv); 177 cmp = (siz[e] > cmp) ? (siz[e]) : (cmp); 178 } 179 if(cmp < maxv) 180 maxv = cmp, G = p; 181 } 182 183 void dfs4(int p, int fa, int dep, int G, int fG) { 184 if(fG) dtf[G].insert(dist(p, fG)); 185 for(int i = 0; i < (signed)g[p].size(); i++) { 186 int e = g[p][i]; 187 if(e == fa || vis[e]) continue; 188 dfs4(e, p, dep + 1, G, fG); 189 } 190 } 191 192 #define get_val(h) (h.size() <= 1) ? ((h.size() == 1) ? (0) : (-1)) : (h.top() + h.sectop()) 193 int dividing(int p, int fag) { 194 dfs2(p, 0); 195 int G, maxv = inf, sG; 196 dfs3(p, 0, siz[p], G, maxv); 197 vis[G] = true, ::fag[G] = fag; 198 dfs4(G, 0, 0, G, fag); 199 dtg[G].insert(0); 200 for(int i = 0; i < (signed)g[G].size(); i++) { 201 int e = g[G][i]; 202 if(vis[e]) continue; 203 sG = dividing(e, G); 204 dtg[G].insert(dtf[sG].top()); 205 } 206 gol.insert(get_val(dtg[G])); 207 return G; 208 } 209 210 void turn_on(int p) { 211 int G = p, oldt = 0, newt = -1; 212 ison[p] = true; 213 while (G) { 214 if(oldt != newt) { 215 gol.remove(get_val(dtg[G])); 216 dtg[G].remove(oldt); 217 if(~newt) dtg[G].insert(newt); 218 gol.insert(get_val(dtg[G])); 219 } 220 if (fag[G]) { 221 oldt = dtf[G].top(); 222 dtf[G].remove(dist(p, fag[G])); 223 newt = dtf[G].top(); 224 } 225 G = fag[G]; 226 } 227 } 228 229 void turn_off(int p) { 230 int G = p, oldt = -1, newt = 0; 231 ison[p] = false; 232 while (G) { 233 if(oldt != newt) { 234 gol.remove(get_val(dtg[G])); 235 if(~oldt) dtg[G].remove(oldt); 236 dtg[G].insert(newt); 237 gol.insert(get_val(dtg[G])); 238 } 239 if(fag[G]) { 240 oldt = dtf[G].top(); 241 dtf[G].insert(dist(p, fag[G])); 242 newt = dtf[G].top(); 243 } 244 G = fag[G]; 245 } 246 } 247 248 inline void solve() { 249 scanf("%d", &m); 250 char buf[10]; 251 int x; 252 while (m--) { 253 scanf("%s", buf); 254 if(buf[0] == 'G') { 255 int x = gol.top(); 256 printf("%d\n", x); 257 } else { 258 scanf("%d", &x); 259 if(ison[x]) 260 turn_off(x); 261 else 262 turn_on(x); 263 } 264 } 265 } 266 267 int main() { 268 init(); 269 init_st(); 270 dividing(1, 0); 271 solve(); 272 return 0; 273 }