CF375D Tree and Queries(dsu)
思路:
开个桶表示每个颜色出现的次数,再用\(d[i]\)数组表示出现次数\(>=i\)的颜色个数。
注意计算贡献时的细节。
if(c==-1)
d[val[col[u]]]+=c;
val[col[u]]+=c;
if(c==1)
d[val[col[u]]]+=c;
如果是消除贡献,先修改\(d\)数组,再修改桶;
如果是增加贡献,先修该桶,再修改\(d\)数组。
代码:
const int maxn=100000+100;
int n,m,col[maxn],ans[maxn];
vector<int>g[maxn];
struct node{
int id,k;
};
vector<node>qask[maxn];
int son[maxn],siz[maxn],Son;
void dfs1(int u,int fa){
siz[u]=1;
for(int i=0;i<g[u].size();i++){
int j=g[u][i];
if(j==fa) continue;
dfs1(j,u);
siz[u]+=siz[j];
if(siz[j]>siz[son[u]]||son[u]==0) son[u]=j;
}
}
int d[maxn],val[maxn],st[maxn];
void add(int u,int f,int c){
if(c==-1)
d[val[col[u]]]+=c;
val[col[u]]+=c;
if(c==1)
d[val[col[u]]]+=c;
for(int i=0;i<g[u].size();i++){
int j=g[u][i];
if(j==f||st[j]) continue;
add(j,u,c);
}
}
void dfs2(int u,int fa,int op){
for(int i=0;i<g[u].size();i++){
int j=g[u][i];
if(j==fa||j==son[u]) continue;
dfs2(j,u,1);
}
if(son[u]) dfs2(son[u],u,0),st[son[u]]=1;
add(u,fa,1);
for(int i=0;i<qask[u].size();i++){
node t=qask[u][i];
ans[t.id]=d[t.k];
}
if(son[u]) st[son[u]]=0;
if(op) add(u,fa,-1);
}
int main(){
n=read,m=read;
rep(i,1,n) col[i]=read;
rep(i,1,n-1){
int u=read,v=read;
g[u].push_back(v);
g[v].push_back(u);
}
rep(i,1,m){
int u=read,k=read;
qask[u].push_back({i,k});
}
dfs1(1,0);
dfs2(1,0,1);
rep(i,1,m) printf("%d\n",ans[i]);
return 0;
}