树状数组维护下dsu on tree即可.复杂度为O(nloglogn).
#include <bits/stdc++.h> using namespace std; const int N=1e5+50; int c[N],cnt[N],ans[N]; vector<int>v[N]; map<int,bool>mp; struct DSU{ int id,k; }; vector<DSU>ask[N]; int Son,dfn[N],sz[N]; int d[N];//记录大于等于i的颜色数量有多少. int sum[N]; int lowbit(int x) { return x&(-x); } void add(int pos,int val) { while(pos<=N-5) { sum[pos]+=val; pos+=lowbit(pos); } } int query(int pos) { int res=0; while(pos) { res+=sum[pos]; pos-=lowbit(pos); }return res; } void cal(int u,int fa,bool op) { if(op==false) { int p=query(cnt[c[u]])-query(max(cnt[c[u]]-1,0)); if(p) add(cnt[c[u]],-p); } if(op) cnt[c[u]]++; else cnt[c[u]]--; if(op==true) { if(cnt[c[u]]>1) add(cnt[c[u]]-1,-1); add(cnt[c[u]],1); } for(int i=0;i<(int)v[u].size();i++) { int son=v[u][i]; if(son==Son||son==fa) continue; cal(son,u,op); } } void dfs(int u,int fa) { sz[u]=1; for(int i=0;i<(int)v[u].size();i++) { int son=v[u][i]; if(son==fa) continue; dfs(son,u);sz[u]+=sz[son]; if(sz[dfn[u]]<sz[son]) dfn[u]=son; } } void dfs(int u,int fa,bool op) { for(int i=0;i<(int)v[u].size();i++) { int son=v[u][i]; if(son==fa||son==dfn[u]) continue; dfs(son,u,true); }//遍历其轻儿子. if(dfn[u]) dfs(dfn[u],u,false),Son=dfn[u]; cal(u,fa,true); for(int i=0;i<(int)ask[u].size();i++) { int id=ask[u][i].id;int k=ask[u][i].k; ans[id]=query(N-5)-query(k-1); } Son=0; if(op) { cal(u,fa,false); } } int main() { int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",c+i); for(int i=1;i<n;i++) { int x,y; scanf("%d%d",&x,&y); v[x].push_back(y); v[y].push_back(x); } for(int i=1;i<=m;i++) { int V,K; scanf("%d%d",&V,&K); ask[V].push_back({i,K}); } dfs(1,0); dfs(1,0,true); for(int i=1;i<=m;i++) printf("%d\n",ans[i]); return 0; }