HDU4822XSY2021Tri-war
Posted ez-lcw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU4822XSY2021Tri-war相关的知识,希望对你有一定的参考价值。
如果题目中只有两个国家,事情就非常简单了:假设只有国家\(A\)和\(B\),我们先找出\(A\)和\(B\)的最近公共祖先\(lca\),然后找到在路径\(A\longrightarrow lca\longrightarrow B\)上的中点\(mid\),然后分3类讨论:
若\(dis(A,mid)==dis(B,mid)\),则\(A\)在这条路径上能到达的范围是\([A,mid)\),\(B\)在这条路径上能到达的范围是\((mid,B]\)。那么\(A\)在全树所能到达的点数为:
\[ \begincases size[son] & \textif deep[A]>deep[B] & (son=在路径[mid,A]上的mid的儿子)\ n-size[mid] & \textif deep[B]>deep[A] \endcases\]
\(B\)在全树能到达的点数为:
\[ \begincases n-size[mid] & \textif deep[A]>deep[B]\ size[son] & \textif deep[B]>deep[A] & (son=在路径[mid,B]上的mid的儿子) \endcases \]
若\(dis(A,mid)<dis(B,mid)\),则\(A\)在这条路径上能到达的范围是\([A,mid]\),\(B\)在这条路径上能到达的范围是\((mid,B]\)。那么\(A\)在全树所能到达的点数为:
\[ \begincases size[mid] & \textif deep[A]>deep[B]\ n-size[son] & \textif deep[B]>deep[A] & (son=在路径[mid,B]上的mid的儿子) \endcases\]
\(B\)在全树能到达的点数为:
\[ \begincases n-size[mid] & \textif deep[A]>deep[B]\ size[son] & \textif deep[B]>deep[A] & (son=在路径[mid,B]上的mid的儿子) \endcases \]
若\(dis(A,mid)>dis(B,mid)\),那就把\(A\)、\(B\)交换一下就和情况2一样了。
那么对于三个点的情况,只需对于每个点求出与另外两个点所能到的范围,再取并集就好了。
代码如下:
#include<bits/stdc++.h>
#define N 100010
#define LN 18
using namespace std;
struct data
bool opt;
int u;
data();
data(bool a,int b)opt=a,u=b;
;
int t,n,m;
int cnt,head[N],nxt[N<<1],to[N<<1];
int fa[N][LN],d[N],size[N];
void init()
cnt=0;
memset(head,0,sizeof(head));
void adde(int u,int v)
to[++cnt]=v;
nxt[cnt]=head[u];
head[u]=cnt;
void dfs(int u)
size[u]=1;
for(int i=1;i<=17;i++)
fa[u][i]=fa[fa[u][i-1]][i-1];
for(int i=head[u];i;i=nxt[i])
if(to[i]!=fa[u][0])
d[to[i]]=d[u]+1;
fa[to[i]][0]=u;
dfs(to[i]);
size[u]+=size[to[i]];
int lca(int a,int b)
if(d[a]<d[b])
swap(a,b);
for(int i=17;i>=0;i--)
if(d[fa[a][i]]>=d[b])
a=fa[a][i];
if(a==b)
return a;
for(int i=17;i>=0;i--)
if(fa[a][i]!=fa[b][i])
a=fa[a][i],b=fa[b][i];
return fa[a][0];
int up(int u,int d)
for(int i=17;i>=0;i--)
if(d>=(1<<i))
u=fa[u][i],d-=(1<<i);
return u;
data getmid(int x,int y,int lca)
int len=d[x]+d[y]-(d[lca]<<1);
if(d[x]>=d[y]) return data(0,up(x,(len-1)>>1));
return data(1,up(y,len>>1));
int query(int x,int y,int z,int xy,int xz)
data ans1=getmid(x,y,xy),ans2=getmid(x,z,xz);
if(!ans1.opt&&!ans2.opt)
if(d[ans1.u]<d[ans2.u])
swap(ans1,ans2);
return size[ans1.u];
else
if(ans1.opt&&ans2.opt)
if(d[ans1.u]<d[ans2.u])
swap(ans1,ans2);
if(lca(ans1.u,ans2.u)==ans2.u)
return n-size[ans2.u];
return n-size[ans2.u]-size[ans1.u];
else
if(ans1.opt)
swap(ans1,ans2);
if(lca(ans1.u,ans2.u)==ans1.u)
return size[ans1.u]-size[ans2.u];
return size[ans1.u];
int main()
scanf("%d",&t);
while(t--)
init();
scanf("%d",&n);
for(int i=1;i<n;i++)
int u,v;
scanf("%d%d",&u,&v);
adde(u,v),adde(v,u);
d[1]=1;
dfs(1);
scanf("%d",&m);
while(m--)
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
int xy=lca(x,y),xz=lca(x,z),yz=lca(y,z);
printf("%d %d %d\n",query(x,y,z,xy,xz),query(y,x,z,xy,yz),query(z,x,y,xz,yz));
return 0;
以上是关于HDU4822XSY2021Tri-war的主要内容,如果未能解决你的问题,请参考以下文章