思路:
1.题目要求维护的颜色数量,因此和模板类似的考虑什么情况下会对答案产生贡献
2.维护颜色出现的次数,维护出现次数大于的颜色种类数
3.显然出现次数的颜色都对有贡献
4.颜色每次出现,必有
5.将每次查询用容器存储,方便离线操作
复杂度:
MyCode:
#include<bits/stdc++.h> using namespace std; const int maxn=2e5+7,maxm=4e5+7; typedef long long ll; inline ll read(){ ll s = 0, w = 1; char ch = getchar(); while (ch < 48 || ch > 57) { if (ch == '-') w = -1; ch = getchar(); } while (ch >= 48 && ch <= 57) s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar(); return s * w; } int head[maxn],Next[maxm],to[maxm],tot; void add(int x,int y) { to[++tot]=y; Next[tot]=head[x]; head[x]=tot; } int size[maxn],son[maxn]; int ans[maxn],cnt[100007],col[100007],sum[100007]; #define lx first #define ly second vector<pair<int,int> >query[maxn]; bool vis[maxn]; void dfs1(int x,int f) { size[x]=1; for(int i=head[x],v;i;i=Next[i]) { v=to[i]; if(v==f) continue; dfs1(v,x); size[x]+=size[v]; if(size[son[x]]<size[v]) son[x]=v; } } void calc(int x,int f) { sum[col[x]]+=1; cnt[sum[col[x]]]+=1; for(int i=head[x],v;i;i=Next[i]) { v=to[i]; if(v==f||vis[v]) continue; calc(v,x); } } void delet(int x,int f) { cnt[sum[col[x]]]-=1; sum[col[x]]-=1; for(int i=head[x],v;i;i=Next[i]) { v=to[i]; if(v==f) continue; delet(v,x); } } void dfs2(int x,int f,bool opt) { for(int i=head[x],v;i;i=Next[i]) { v=to[i]; if(v==f||son[x]==v) continue; dfs2(v,x,false); } if(son[x]) { dfs2(son[x],x,true); vis[son[x]]=true; } calc(x,f); int size=query[x].size(); for(int i=0;i<size;++i) ans[query[x][i].lx]=cnt[query[x][i].ly]; if(son[x]) vis[son[x]]=false; if(!opt) { delet(x,f); } } int main() { int n=read(),m=read(); for(int i=1;i<=n;++i) col[i]=read(); for(int i=2,u,v;i<=n;++i) { u=read(),v=read(); add(u,v); add(v,u); } for(int i=1,a,k;i<=m;++i) { a=read(),k=read(); query[a].push_back(make_pair(i,k)); } dfs1(1,0); dfs2(1,0,false); for(int i=1;i<=m;++i) printf("%d\n",ans[i]); return 0; }