Codeforces - Misha, Grisha and Underground

題目鏈接:Codeforces - Misha, Grisha and Underground


我們可以枚舉終點,問題就轉變爲a->c和b->c的交點個數。

我們分別考慮b是c到a的子樹中,或者不是,然後可以發現公式:(dis(a,c)+dis(b,c)-dis(a,b))/2+1;


AC代碼:

#pragma GCC optimize("-Ofast","-funroll-all-loops")
#include<bits/stdc++.h>
//#define int long long
using namespace std;
const int N=1e5+10;
int n,q;
int pos[N],bl[N],dep[N],f[N],son[N],sz[N],cnt;
vector<int> g[N];
void dfs1(int x){
	sz[x]=1;
	for(auto to:g[x]){
		if(f[x]==to)	continue;
		f[to]=x;	dep[to]=dep[x]+1;	dfs1(to);	sz[x]+=sz[to];
		if(sz[to]>sz[son[x]])	son[x]=to;
	}
}
void dfs2(int x,int belong){
	pos[x]=++cnt;	bl[x]=belong;
	if(son[x])	dfs2(son[x],belong);
	for(auto to:g[x])	if(to!=son[x]&&dep[to]>dep[x])	dfs2(to,to);
}
inline int lca(int x,int y){
	while(bl[x]!=bl[y]){
		if(dep[bl[x]]<dep[bl[y]])	swap(x,y);	x=f[bl[x]];
	}
	return dep[x]>dep[y]?y:x;
}
inline int dis(int x,int y){return dep[x]+dep[y]-2*dep[lca(x,y)];}
inline int calc(int a,int b,int c){
	return (dis(a,c)+dis(b,c)-dis(a,b))/2+1;
}
signed main(){
	cin>>n>>q;
	for(int i=2,x;i<=n;i++)	scanf("%d",&x),g[x].push_back(i);
	dfs1(1),dfs2(1,1);
	for(int i=1,a,b,c;i<=q;i++){
		scanf("%d %d %d",&a,&b,&c);
		printf("%d\n",max(calc(a,b,c),max(calc(a,c,b),calc(b,c,a))));
	}
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章