A组LCA简单变形(速度有点慢不过可以ac)
作者:
炽热小老弟
,
2024-05-05 21:24:15
,
所有人可见
,
阅读 13
#include<iostream>
#include<algorithm>
#include<cstring>
#include<map>
using namespace std;
const int N=100010,M=2*N;
int n,Q;
int h[N],e[M],ne[M],idx;
int q[N];//最近公共祖先
int fa[N][18],depth[N];
int dp[N][22];//1---20呗 记录总类数量
int DP[N][22];//这里是不累加的 就是节点上本来有谁
void add(int a,int b)
{
e[idx]=b;ne[idx]=h[a];h[a]=idx++;
}
void bfs(int root)
{
int hh=0,tt=-1;
q[++tt]=root;
memset(depth,0x3f,sizeof depth);
depth[0]=0,depth[root]=1;
while(hh<=tt)
{
auto t=q[hh++];
for(int i=h[t];~i;i=ne[i])
{
int j=e[i];
if(depth[j]>depth[t]+1)
{
depth[j]=depth[t]+1;
q[++tt]=j;
for(int i=1;i<=20;i++)
dp[j][i]+=dp[t][i];//有多少我加多少
fa[j][0]=t;
for(int k=1;k<=17;k++)
fa[j][k]=fa[fa[j][k-1]][k-1];
}
}
}
}
int lca(int a,int b)
{
if(depth[a]<depth[b]) swap(a,b);
for(int k=17;~k;k--)
{
if(depth[fa[a][k]]>=depth[b])
a=fa[a][k];
}
if(a==b) return a;
for(int k=17;~k;k--)
{
if(fa[a][k]!=fa[b][k])
{
a=fa[a][k];
b=fa[b][k];
}
}
return fa[a][0];
}
int main()
{
cin.tie(0);
memset(h,-1,sizeof h);
cin>>n>>Q;
for(int i=1;i<=n;i++)
{
int x;
cin>>x;
dp[i][x]++;//这里种类+1
DP[i][x]++;
}
for(int i=0;i<n-1;i++)
{
int a,b;
cin>>a>>b;
add(a,b),add(b,a);
}
int root=1;//1--n;
bfs(root);
int res=0;
while(Q--)
{
res=0;
int a,b;
cin>>a>>b;
int p=lca(a,b);
for(int i=1;i<=20;i++)
res=res+(dp[a][i]+dp[b][i]-2*dp[p][i]+DP[p][i]?1:0);//应该不会负数吧
cout<<res<<endl;
}
return 0;
}
二刷 发现写错了hhh 正好把造的2样例过了 应该是或
看了半天发现是对的 妈的