http://codeforces.com/problemset/problem/375/D
树莫队就是把树用dfs序变成线性的数组。 (原数组要根据dfs的顺序来变化)
然后和莫队一样的区间询问。
这题和普通莫队有点区别,他需要的不单单是统计区间元素种类个数,是区间元素种类个数 >= k[i]的个数。
考虑最简单的用bit维护,复杂度多了个log
观察到每次只需要 + 1 或者 -1
用一个数组sum[k]表示种类数大于等于k的ans
在numc[val]++之后,sum[numc[val]]++,表明这个种类出现次数是numc[val]次的贡献递增1
在num[val]--之前,就需要把sum[numc[val]]--,表明贡献减1了
#include <bits/stdc++.h> #define IOS ios::sync_with_stdio(false) using namespace std; #define inf (0x3f3f3f3f) typedef long long int LL; const int maxn = 1e5 + 20; struct Edge { int u, v, tonext; }e[maxn * 2]; int first[maxn], num; int c[maxn]; void addEdge(int u, int v) { ++num; e[num].u = u, e[num].v = v, e[num].tonext = first[u]; first[u] = num; } int L[maxn], R[maxn], dfs_clock; int color[maxn]; void dfs(int cur, int fa) { L[cur] = ++dfs_clock; color[dfs_clock] = c[cur]; for (int i = first[cur]; i; i = e[i].tonext) { int v = e[i].v; if (fa == v) continue; dfs(v, cur); } R[cur] = dfs_clock; } int magic; struct Node { int L, R, k, id; bool operator < (const struct Node & rhs) const { if (L / magic != rhs.L / magic) return L / magic < rhs.L / magic; else return R < rhs.R; } }query[maxn]; int ans[maxn], numc[maxn]; int bit[maxn]; int lowbit(int x) { return x & (-x); } void add(int pos, int val) { while (pos) { bit[pos] += val; pos -= lowbit(pos); } } int ask(int pos) { int ans = 0; while (pos <= maxn - 20) { ans += bit[pos]; pos += lowbit(pos); } return ans; } int suffix[maxn]; void work() { int n, m; cin >> n >> m; for (int i = 1; i <= n; ++i) cin >> c[i]; for (int i = 1; i <= n - 1; ++i) { int u, v; scanf("%d%d", &u, &v); addEdge(u, v); addEdge(v, u); } dfs(1, 0); magic = (int)sqrt(n + 0.5); for (int i = 1; i <= m; ++i) { int which, k; scanf("%d%d", &which, &k); query[i].L = L[which], query[i].R = R[which], query[i].k = k; query[i].id = i; } sort(query + 1, query + 1 + m); int L = 1, R = 0; int temp = 0; for (int i = 1; i <= m; ++i) { while (R < query[i].R) { ++R; suffix[++numc[color[R]]]++; } while (R > query[i].R) { suffix[numc[color[R]]--]--; --R; } while (L < query[i].L) { suffix[numc[color[L]]--]--; L++; } while (L > query[i].L) { L--; suffix[++numc[color[L]]]++; } ans[query[i].id] = suffix[query[i].k]; } for (int i = 1; i <= m; ++i) { printf("%d ", ans[i]); } } int main() { #ifdef local freopen("data.txt", "r", stdin); // freopen("data.txt", "w", stdout); #endif work(); return 0; }