很容易想到离线的做法,倍增往上找,然后整个dfs一遍,但是需要用到树状数组
顺便,求log2(x)千万别写log(x) / log(2),精度会出问题,直接写log2(x)就行了
#include <bits/stdc++.h> using namespace std; const int N = 1e5 + 10; int age[N], maxn[N][21], fa[N][21], dep[N], ans[N]; vector < int > v[N], point[N]; void dfs1(int u, int f) { dep[u] = dep[f] + 1; fa[u][0] = f; maxn[u][0] = max(age[u], age[f]); for (int i = 1; i <= 20; i++) { maxn[u][i] = max(maxn[u][i - 1], maxn[fa[u][i - 1]][i - 1]); fa[u][i] = fa[fa[u][i - 1]][i - 1]; } for (int i = 0; i < v[u].size(); i++) { int e = v[u][i]; if (e != f) dfs1(e, u); } } int c[N]; inline int lowbit(int x) { return x & (-x); } inline void add(int pos, int val) { for (int i = pos; i < N; i += lowbit(i)) c[i] += val; } inline int query(int val) { int ans = 0; for (int i = val; i > 0; i -= lowbit(i)) ans += c[i]; return ans; } void dfs(int u, int f) { for (int i = 0; i < point[u].size(); i++) { int e = point[u][i]; add(e, 1); } ans[u] = query(age[u]); for (int i = 0; i < v[u].size(); i++) { int e = v[u][i]; if (e == f) continue; dfs(e, u); } for (int i = 0; i < point[u].size(); i++) { int e = point[u][i]; add(e, -1); } } int main() { int n, m; scanf("%d %d", &n, &m); for (int i = 1; i <= n; i++) { int a, b; scanf("%d %d", &a, &b); age[i] = a; v[b].push_back(i); } dfs1(1, 1); for (int i = 1; i <= m; i++) { int o, l, r; scanf("%d %d %d", &o, &l, &r); int p = o; if (o == 1) { point[o].push_back(l); continue; } int sz = log2(dep[o] - 1); for (int j = sz; j >= 0; j--) { if (maxn[p][j] <= r) p = fa[p][j]; } point[p].push_back(l); } dfs(1, 1); for (int i = 1; i <= n; i++) printf("%d ", ans[i]); return 0; }