题意:
给出一颗以\(1\)为根的有根树,每个结点有个颜色\(c_i\)。
之后要回答\(m\)组询问,每组询问包含\(v_i,k_i\),要回答以\(v_i\)为根的子树中,颜色出现次数不小于\(k_i\)的颜色的和。
思路:
- 这种静态子树上的问题,可以考虑dsu on tree。
- 由于要回答次数超过\(k\)的颜色和,那么建立一颗线段树,以出现次数为横坐标,维护颜色的和。
由于\(dsu\ on\ tree\),每个点会被访问\(O(logn)\)次,因为每个结点有修改操作,所以会多个\(log\)的时间复杂度。
总的时间复杂度为\(O(nlog^2n)\)。
/* * Author: heyuhhh * Created Time: 2019/11/13 19:24:01 */ #include <bits/stdc++.h> #define MP make_pair #define fi first #define se second #define sz(x) (int)(x).size() #define all(x) (x).begin(), (x).end() #define INF 0x3f3f3f3f #define Local #ifdef Local #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0) void err() { std::cout << '\n'; } template<typename T, typename...Args> void err(T a, Args...args) { std::cout << a << ' '; err(args...); } #else #define dbg(...) #endif void pt() {std::cout << '\n'; } template<typename T, typename...Args> void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); } using namespace std; typedef long long ll; typedef pair<int, int> pii; //head const int N = 1e5 + 5; int n, m; int c[N]; vector <int> g[N], v[N]; struct Q { int k, id; }q[N]; int sz[N], bson[N]; void dfs(int u, int fa) { sz[u] = 1; int mx = 0; for(auto v : g[u]) if(v != fa) { dfs(v, u); sz[u] += sz[v]; if(sz[v] > mx) mx = sz[v], bson[u] = v; } } int son; int ans[N], cnt[N]; int sum[N << 2]; void upd(int o, int l, int r, int p, int val) { sum[o] += val; if(l == r) return; int mid = (l + r) >> 1; if(p <= mid) upd(o << 1, l, mid, p, val); else upd(o << 1|1, mid + 1, r, p, val); } int query(int o, int l, int r, int k) { if(l == r) return sum[o]; int mid = (l + r) >> 1; if(k <= mid) return query(o << 1, l, mid, k) + sum[o << 1|1]; return query(o << 1|1, mid + 1, r, k); } void add(int u, int fa, int val) { if(cnt[c[u]]) upd(1, 1, n, cnt[c[u]], -1); cnt[c[u]] += val; if(cnt[c[u]]) upd(1, 1, n, cnt[c[u]], 1); for(auto v : g[u]) if(v != fa && v != son) { add(v, u, val); } } void dfs2(int u, int fa, int op) { for(auto v : g[u]) if(v != fa && v != bson[u]) { dfs2(v, u, 0); } if(bson[u]) dfs2(bson[u], u, 1); son = bson[u]; add(u, fa, 1); for(auto i : v[u]) { ans[q[i].id] = query(1, 1, n, q[i].k); } son = 0; if(!op) add(u, fa, -1); } void run(){ for(int i = 1; i <= n; i++) cin >> c[i]; for(int i = 1; i < n; i++) { int u, v; cin >> u >> v; g[u].push_back(v); g[v].push_back(u); } dfs(1, 0); for(int i = 1; i <= m; i++) { int x, k; cin >> x >> k; v[x].push_back(i); q[i] = Q{k, i}; } dfs2(1, 0, 1); for(int i = 1; i <= m; i++) cout << ans[i] << "\n"; } int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cout << fixed << setprecision(20); while(cin >> n >> m) run(); return 0; }