dsu on treeios
點我跳轉c++
給定一棵 \(n\) 個節點的樹,根節點爲 \(1\)。每一個節點上有一個顏色 \(c_i\)
\(m\) 次詢問。
每次詢問給出 \(u\) \(k\):詢問在以 \(u\) 爲根的子樹中,出現次數 \(≥k\) 的顏色有多少種。ui
能夠開棵權值線段樹spa
若是當前顏色出現的次數 \(cnt[i] = x\), 就把樹的第 \(x\) 個位置的值 \(+ 1\)code
那麼對於每一個詢問的 \(k\) 輸出樹的第 \(k\) 個位置的值便可ci
#include<bits/stdc++.h> #define rep(i,a,n) for (int i=a;i<=n;i++) #define per(i,n,a) for (int i=n;i>=a;i--) #define int long long #define pb push_back #define fi first #define se second using namespace std; const int N = 3e5 + 10; struct Tree{ int l , r , lazy , sum; }tree[N << 2]; void push_up(int rt) { tree[rt].sum = tree[rt << 1].sum + tree[rt << 1 | 1].sum; } void push_down(int rt) { int x = tree[rt].lazy; tree[rt].lazy = 0; tree[rt << 1].lazy = tree[rt << 1 | 1].lazy = x; tree[rt << 1].sum += (tree[rt << 1].r - tree[rt << 1].l + 1) * x; tree[rt << 1 | 1].sum += (tree[rt << 1 | 1].r - tree[rt << 1 | 1].l + 1) * x; } void build(int l , int r , int rt) { tree[rt].l = l , tree[rt].r = r , tree[rt].lazy = 0; if(l == r) { tree[rt].sum = 0; return ; } int mid = l + r >> 1; build(l , mid , rt << 1); build(mid + 1 , r , rt << 1 | 1); push_up(rt); } void update_range(int L , int R , int rt , int val) { int l = tree[rt].l , r = tree[rt].r; if(L <= l && r <= R) { tree[rt].lazy += val; tree[rt].sum += (r - l + 1) * val; return ; } push_down(rt); int mid = l + r >> 1; if(L <= mid) update_range(L , R , rt << 1 , val); if(R > mid) update_range(L , R , rt << 1 | 1 , val); push_up(rt); } int query_range(int L , int R , int rt) { int l = tree[rt].l , r = tree[rt].r; if(L <= l && r <= R) return tree[rt].sum; push_down(rt); int mid = l + r >> 1 , ans = 0; if(L <= mid) ans += query_range(L , R , rt << 1); if(R > mid) ans += query_range(L , R , rt << 1 | 1); return ans; } struct Edge{ int nex , to; }edge[N << 1]; int head[N] , TOT; void add_edge(int u , int v) { edge[++ TOT].nex = head[u] ; edge[TOT].to = v; head[u] = TOT; } int dep[N] , sz[N] , hson[N] , HH; int col[N] , n , m , up; int cnt[N] , sum[N]; vector<pair<int , int>>Q[N] , ans; void dfs(int u , int far) { dep[u] = dep[far] + 1; sz[u] = 1; for(int i = head[u] ; i ; i = edge[i].nex) { int v = edge[i].to; if(v == far) continue ; dfs(v , u); sz[u] += sz[v]; if(sz[v] > sz[hson[u]]) hson[u] = v; } } void calc(int u , int far, int val) { cnt[col[u]] += val; if(val == 1) { int k = cnt[col[u]]; update_range(k , k , 1 , 1); } if(val == -1) { int k = cnt[col[u]] + 1; update_range(k , k , 1 , -1); } for(int i = head[u] ; i ; i = edge[i].nex) { int v = edge[i].to; if(v == far || v == HH) continue ; calc(v , u , val); } } void dsu(int u , int far , int op) { for(int i = head[u] ; i ; i = edge[i].nex) { int v = edge[i].to; if(v == far || v == hson[u]) continue ; dsu(v , u , 0); } if(hson[u]) dsu(hson[u] , u , 1) , HH = hson[u]; calc(u , far , 1); for(auto i : Q[u]) { int id = i.fi , k = i.se; int res = query_range(k , k , 1); ans.pb(make_pair(id , res)); } HH = 0; if(!op) calc(u , far , -1); } signed main() { ios::sync_with_stdio(false); cin.tie(0) , cout.tie(0); cin >> n >> m; rep(i , 1 , n) cin >> col[i]; rep(i , 1 , n - 1) { int u , v; cin >> u >> v; add_edge(u , v) , add_edge(v , u); } rep(i , 1 , m) { int u , k; cin >> u >> k; Q[u].pb(make_pair(i , k)); } build(1 , 100000 , 1); dfs(1 , 0); dsu(1 , 0 , 0); sort(ans.begin() , ans.end()); for(auto i : ans) cout << i.se << '\n'; return 0; }