思路:
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;
} 
京公网安备 11010502036488号