括号序分块
略。
王室联邦分块
Luogu P2325 SCOI2005 王室联邦
sizbl 为一预定好的值,分得的块的大小范围 [sizbl,3sizbl),且 ≥2sizbl 的块最多只有一个。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| int sizbl = 100, cntbl, root[MAXn + 10]; int inbl[MAXn + 10]; int top, stk[MAXn + 10]; void EvaBl(int cur, int f) { int bottom = top; for (int i = head[cur]; i; i = nex[i]) { if (to[i] == f) continue; EvaBl(to[i], cur); if (top - bottom >= sizbl) { root[++cntbl] = cur; while (top > bottom) { inbl[stk[top--]] = cntbl; } } } stk[++top] = cur; }
signed main() { EvaBl(1, 0); if (cntbl == 0) root[++cntbl] = 1; while (top) inbl[stk[top--]] = cntbl; }
|
树上撒点
按深度从大往小遍历每个点,如果其 0∼sizbl 级祖先中没有关键点,则将其 sizbl 级祖先作为关键点。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| int cntkey, idxkey[MAXn + 10]; int top[MAXn + 10]; bitset<MAXn + 10> info[MAXsqrtn + 10]; int tpstk, stk[MAXn + 10]; void PutKey(int root) { while (!pq.empty()) { pair<int, int> pr = pq.top(); pq.pop(); int cur = pr.second; for (int i = 0; i <= sizbl && cur && idxkey[cur] == 0; ++i, cur = fa[cur]); if (idxkey[cur] == 0) { idxkey[cur] = ++cntkey; } } for (int i = 1; i <= n; ++i) { if (i == root) continue; pq.push(make_pair(dep[i], i)); } while (!pq.empty()) { pair<int, int> pr = pq.top(); pq.pop(); int cur = pr.second; if (top[cur]) continue; if (idxkey[cur]) { info[idxkey[pr.second]].set(a[cur], 1); stk[++tpstk] = cur; for (cur = fa[cur]; cur && idxkey[cur] == 0; cur = fa[cur]) { info[idxkey[pr.second]].set(a[cur], 1); stk[++tpstk] = cur; } while (tpstk) { top[stk[tpstk--]] = cur; } } else { stk[++tpstk] = cur; for (cur = fa[cur]; cur && idxkey[cur] == 0; cur = fa[cur]) { stk[++tpstk] = cur; } while (tpstk) { top[stk[tpstk--]] = cur; } } } } int Query(int x, int y) { bitset<MAXn + 10> ans; while (top[x] != top[y]) { if (dep[top[x]] > dep[top[y]]) swap(x, y); if (idxkey[y]) { ans = ans | info[idxkey[y]]; y = top[y]; } else { ans.set(a[y], 1); y = fa[y]; } } while (x != y) { if (dep[x] > dep[y]) swap(x, y); ans.set(a[y], 1); y = fa[y]; } ans.set(a[x], 1); return ans.count(); }
|