Misha, Grisha and Underground CodeForces - 832D (倍增树上求LCA)

Posted qieqiemin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Misha, Grisha and Underground CodeForces - 832D (倍增树上求LCA)相关的知识,希望对你有一定的参考价值。

Misha and Grisha are funny boys, so they like to use new underground. The underground has n stations connected with n - 1 routes so that each route connects two stations, and it is possible to reach every station from any other.

The boys decided to have fun and came up with a plan. Namely, in some day in the morning Misha will ride the underground from station s to station f by the shortest path, and will draw with aerosol an ugly text "Misha was here" on every station he will pass through (including s and f). After that on the same day at evening Grisha will ride from station t to station f by the shortest path and will count stations with Misha‘s text. After that at night the underground workers will wash the texts out, because the underground should be clean.

The boys have already chosen three stations ab and c for each of several following days, one of them should be station s on that day, another should be station f, and the remaining should be station t. They became interested how they should choose these stations sft so that the number Grisha will count is as large as possible. They asked you for help.

Input

The first line contains two integers n and q (2 ≤ n ≤ 1051 ≤ q ≤ 105) — the number of stations and the number of days.

The second line contains n - 1 integers p2, p3, ..., pn (1 ≤ pi ≤ n). The integer pimeans that there is a route between stations pi and i. It is guaranteed that it‘s possible to reach every station from any other.

The next q lines contains three integers ab and c each (1 ≤ a, b, c ≤ n) — the ids of stations chosen by boys for some day. Note that some of these ids could be same.

Output

Print q lines. In the i-th of these lines print the maximum possible number Grisha can get counting when the stations st and f are chosen optimally from the three stations on the i-th day.

Examples

Input
3 2
1 1
1 2 3
2 3 3
Output
2
3
Input
4 1
1 2 3
1 2 3
Output
2

Note

In the first example on the first day if s = 1, f = 2, t = 3, Misha would go on the route 技术图片 2, and Grisha would go on the route 技术图片 技术图片 2. He would see the text at the stations 1 and 2. On the second day, if s = 3, f = 2, t = 3, both boys would go on the route 技术图片 技术图片 2. Grisha would see the text at 3 stations.

In the second examle if s = 1, f = 3, t = 2, Misha would go on the route 技术图片 技术图片3, and Grisha would go on the route 技术图片 3 and would see the text at both stations.

 

题意:给定一个含有N个节点的树,和Q个群问,每一个询问包括三个整数,a,b,c 。 让求出这三个整数构成的两个路径中交点个数的最大值。

思路:

首先我们应该知道这样的问题,如果这三个整数构成了这样的两个路径,a到b,和,c到b  这两个路径。

定义a到b的距离是lab,其他类推。那么这两个路径的交点个数是 ( lab + lbc - lac ) / 2 + 1

那么我们用倍增在线LCA求任意两个节点的最短路径的距离,然后枚举a,b,c分别做为交点的路径情况的最大值即是答案。

细节见代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
#define ALL(x) (x).begin(), (x).end()
#define dll(x) scanf("%I64d",&x)
#define xll(x) printf("%I64d
",x)
#define sz(a) int(a.size())
#define all(a) a.begin(), a.end()
#define rep(i,x,n) for(int i=x;i<n;i++)
#define repd(i,x,n) for(int i=x;i<=n;i++)
#define pii pair<int,int>
#define pll pair<long long ,long long>
#define gbtb ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define MS0(X) memset((X), 0, sizeof((X)))
#define MSC0(X) memset((X), ‘‘, sizeof((X)))
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define eps 1e-6
#define gg(x) getInt(&x)
#define db(x) cout<<"== [ "<<x<<" ] =="<<endl;
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b){return a/gcd(a,b)*b;}
ll powmod(ll a,ll b,ll MOD){ll ans=1ll;while(b){if(b&1)ans=ans*a%MOD;a=a*a%MOD;b>>=1;}return ans;}
inline void getInt(int* p);
const int maxn=1000010;
const int inf=0x3f3f3f3f;
/*** TEMPLATE CODE * * STARTS HERE ***/
const int N = 1e5+7;
std::vector<int> son[N];
int depth[N],fa[N][21],in[N],a,b;
// depth[i] -> i 节点的深度
// fa[i][j] -> i 节点向上移动2^j个节点后的祖先
// fa[i][0] -> i 向上移动1个节点后的祖先,即父节点
// in[i] i节点的入度,用来找树根用的。
// a b 为读边用的。
int n;
int m;
void buildtree()
{
    for(int i=2;i<=n;i++)
    {
        a=i;
        scanf("%d",&b);
        son[a].push_back(b);
        son[b].push_back(a);
    }
}
void dfs(int rt,int prev)
{
    depth[rt]=depth[prev]+1;
    fa[rt][0]=prev;
    for(int i=1;i<20;i++)
    {
        fa[rt][i]=fa[fa[rt][i-1]][i-1];
    }
    for(int i=0;i<son[rt].size();i++)
    {
        if(son[rt][i]==prev)
            continue;
        dfs(son[rt][i],rt);
    }
}
int LCA(int x,int y)
{
    if(depth[x]<depth[y])
        swap(x,y);
    for(int i=19;i>=0;i--)
    {
        if(depth[x]-(1<<i)>=depth[y])
        {
            x=fa[x][i];
        }
    }
    if(x==y)
    {
        return x;
    }
    for(int i=19;i>=0;i--)
    {
        if(fa[x][i]!=fa[y][i])
        {
            x=fa[x][i];
            y=fa[y][i];
        }
    }
    return fa[x][0];
}
int dist(int a,int b)
{
    int u=LCA(a,b);
    int L=depth[a]+depth[b]-2*depth[u];
    return L;
}
int main()
{
    //    freopen("C:\Users\DH_M\Desktop\code_io\in.txt.txt","r",stdin);
    //    freopen("C:\Users\DH_M\Desktop\code_io\out.txt.txt","w",stdout);
    scanf("%d",&n);
    scanf("%d",&m);
    buildtree();
    depth[0]=-1;
    int rt=1;// root 
    dfs(rt,rt);
    int c;
    for(int i=1;i<=m;i++)
    {
        scanf("%d %d %d",&a,&b,&c);
        int ans=0;
        int lab,lbc,lac,l1,l2,l3;
        lac=dist(a,c);
        lab=dist(a,b);
        lbc=dist(b,c);
        l1=(lab+lbc-lac)/2;
        l2=(lab+lac-lbc)/2;
        l3=(lac+lbc-lab)/2;
        ans=max(l1,max(l2,l3));
        printf("%d
",ans+1);
    }
    return 0;
}

inline void getInt(int* p) {char ch;do {ch = getchar();} 
while (ch ==   || ch == 
);if (ch == -) {*p = -(getchar() - 0);
while ((ch = getchar()) >= 0 && ch <= 9) {*p = *p * 10 - ch + 0;}}
else {*p = ch - 0;while ((ch = getchar()) >= 0 && ch <= 9) 
{*p = *p * 10 + ch - 0;}}}

 

以上是关于Misha, Grisha and Underground CodeForces - 832D (倍增树上求LCA)的主要内容,如果未能解决你的问题,请参考以下文章

Misha, Grisha and Underground CodeForces - 832D (倍增树上求LCA)

[CF832D] Misha, Grisha and Underground

Codeforces Round #425 (Div. 2) D. Misha, Grisha and Underground

Codeforces Round #425 (Div. 2) Problem D Misha, Grisha and Underground (Codeforces 832D) - 树链剖分 - 树状

Misha and Changing Handles

CodeForces 501B Misha and Changing Handles(STL map)