1 条题解
-
3
CF208E 题解
给定一片 个点的森林,森林中的树都有根。 次询问,每次询问一个点 与多少个点有相同的 级祖先。 ,
离线做法,首先用倍增对于每个询问求出 的 级祖先,用 或链表把询问挂在祖先上,问题转换成求一个点有多少个 级儿子的问题。
对每个节点,以深度为下标建立权值线段树,进行 。若 到一个节点 ,在线段树插入当前点的深度并与子节点的线段树合并。然后遍历所有询问,对于询问这个点有多少个 级儿子,在线段树中查询深度为 的节点有多少个即可。别忘了答案要减一。
时间复杂度 。
CODE
#include <bits/stdc++.h> using namespace std; inline int read() { int x = 0, f = 0; char c = 0; while (!isdigit(c)) f |= c == '-', c = getchar(); while (isdigit(c)) x = (x << 3) + (x << 1) + (c ^ 48), c = getchar(); return f ? -x : x; } #define N 100010 #define pb push_back #define PII pair<int, int> #define mp make_pair #define fi first #define se second int n, m, res[N], f[N][22], rt[N], dep[N]; vector<int> e[N], root; vector<PII> q[N]; struct Segment_tree { int l, r, ls, rs, sum; #define lid tr[id].ls #define rid tr[id].rs }tr[N * 20]; int cnt = 0; void Add(int &id, int l, int r, int x) { if (!id) id = ++ cnt; tr[id].l = l, tr[id].r = r; if (l == r) { tr[id].sum ++; return; } int mid = tr[id].l + tr[id].r >> 1; if (x <= mid) Add(lid, l, mid, x); if (x > mid) Add(rid, mid + 1, r, x); } int Ask(int id, int l, int r, int x) { if (!id) return 0; if (l == r) return tr[id].sum; int mid = tr[id].l + tr[id].r >> 1; if (x <= mid) return Ask(lid, l, mid, x); if (x > mid) return Ask(rid, mid + 1, r, x); } void Merge(int &x, int y, int l, int r) { if (!x || !y) return x += y, void(); if (l == r) { tr[x].sum += tr[y].sum; return; } int mid = tr[x].l + tr[x].r >> 1; Merge(tr[x].ls, tr[y].ls, l, mid); Merge(tr[x].rs, tr[y].rs, mid + 1, r); } void dfs2(int x, int fa) { Add(rt[x] = ++ cnt, 1, n, dep[x]); for (auto y : e[x]) if (y != fa) { dfs2(y, x), Merge(rt[x], rt[y], 1, n); } for (auto i : q[x]) { res[i.fi] = Ask(rt[x], 1, n, dep[x] + i.se) - 1; } } void dfs1(int x, int fa) { dep[x] = dep[fa] + 1; f[x][0] = fa; for (int i = 1; i <= 20; i ++) { f[x][i] = f[f[x][i - 1]][i - 1]; } for (auto y : e[x]) { if (y != fa) dfs1(y, x); } } int main() { n = read(); for (int i = 1; i <= n; i ++) { int x = read(); if (x) e[x].pb(i), e[i].pb(x); else root.pb(i); } for (auto x : root) dfs1(x, 0); m = read(); for (int i = 1; i <= m; i ++) { int x = read(), y = read(), fa = x; for (int i = 0, j = y; i <= 20; i ++, j >>= 1) { if (j & 1) fa = f[fa][i]; } q[fa].pb(mp(i, y)); } for (auto x : root) dfs2(x, 0); for (int i = 1; i <= m; i ++) { printf("%d ", res[i]); } puts(""); return 0; }
- 1
信息
- ID
- 6114
- 时间
- 2000ms
- 内存
- 256MiB
- 难度
- 7
- 标签
- 递交数
- 2
- 已通过
- 2
- 上传者