题解:P10391 [蓝桥杯 2024 省 A] 零食采购
Breath_of_the_Wild · · 题解
题目要我们求
我的做法:先预处理出一个 cnt[i][j] 表示从根节点(自己设定)出发,到
这个
for(int i=1;i<=22;i++){
cnt[u][i]=cnt[x][i];
}
cnt[u][c[u]]++;
接着就是重点了。我们求
其中
不会 LCA 的请移步 P3379。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5,K=22;
int n,q,c[N],u,v,s,t,st[N][K+2],dep[N],cnt[N][K+2];
vector<int> g[N];
void dfs(ll x,ll fx){
dep[x]=dep[fx]+1,st[x][0]=fx;
for(ll i=1;i<=K;i++){
st[x][i]=st[st[x][i-1]][i-1];
}
for(ll u:g[x]){
if(u!=fx) dfs(u,x);
}
}
int LCA(int x,int y){
if(dep[x]<dep[y]) swap(x,y);
for(ll i=K;i>=0;i--){
ll fx=st[x][i];
if(dep[fx]>=dep[y]) x=fx;
}
if(x==y) return x;
for(int i=20;i>=0;i--){
ll fa=st[x][i],fb=st[y][i];
if(fa!=fb) x=fa,y=fb;
}
return st[x][0];
}
void DFS(int x,int fx){
for(int u:g[x]){
if(u==fx||u==x) continue;
for(int i=1;i<=22;i++){
cnt[u][i]=cnt[x][i];
}
cnt[u][c[u]]++;
DFS(u,x);
}
}
int main(){
cin>>n>>q;
for(int i=1;i<=n;i++){
cin>>c[i];
}
for(int i=1;i<n;i++){
cin>>u>>v;
g[u].push_back(v);
g[v].push_back(u);
}
dfs(1,1);
cnt[1][c[1]]++;
DFS(1,1);
while(q--){
cin>>s>>t;
int ans=0,lc=LCA(s,t);
for(int i=1;i<=22;i++){
int tt=0;
if(c[lc]==i) tt=1;
if(cnt[s][i]+cnt[t][i]-2*cnt[lc][i]+tt>0) ans++;
}
cout<<ans<<'\n';
}
return 0;
}