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 ≤ 105, 1 ≤ 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 21 11 2 32 3 3

Output

23

Input

4 11 2 31 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 1  2, and Grisha would go on the route 3  1  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 3  1  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 1  2 3, and Grisha would go on the route 2  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\n",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), ‘\0‘, 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\n",ans+1);
    }
    return 0;
}

inline void getInt(int* p) {char ch;do {ch = getchar();}
while (ch == ‘ ‘ || ch == ‘\n‘);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‘;}}}

原文地址:https://www.cnblogs.com/qieqiemin/p/10415424.html

时间: 2024-09-28 07:31:47

Misha, Grisha and Underground CodeForces - 832D (倍增树上求LCA)的相关文章

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

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 h

Codeforces 832D - Misha, Grisha and Underground

832D - Misha, Grisha and Underground 思路:lca,求两个最短路的公共长度.公共长度公式为(d(a,b)+d(b,c)-d(a,c))/2. 代码: #include<bits/stdc++.h> using namespace std; #define ll long long #define ls rt<<1,l,m #define rs rt<<1|1,m+1,r const int INF=0x3f3f3f3f; const

Codeforces 832 D Misha, Grisha and Underground

Misha, Grisha and Underground 题意:Misha 和 Grisha 是2个很喜欢恶作剧的孩子, 每天早上 Misha 会从地铁站 s 通过最短的路到达地铁站 f, 并且在每个地铁站上都写上一句话, 然后Grisha 再从地铁站 t 通过最短的路到达地铁站 f, 并且记录下路途上被Misha写上字的地铁站数目,并且当天晚上会人会将地铁站清理干净,不会干扰第二天的计数, 现在给你3个地铁站 a, b, c, 现在求Misha记录的数目最大能是多少. 代码:求出Lca(a,

poj1330Nearest Common Ancestors以及讲解倍增法求lca

Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 20487   Accepted: 10784 Description A rooted tree is a well-known data structure in computer science and engineering. An example is shown below: In the figure, each node is labeled with an

倍增法求LCA

倍增法求LCA LCA(Least Common Ancestors)的意思是最近公共祖先,即在一棵树中,找出两节点最近的公共祖先. 倍增法是通过一个数组来实现直接找到一个节点的某个祖先,这样我们就可以在O(logn)的时间内求出求出任意节点的任意祖先. 然后先把两个节点中转化为深度相同的节点,然后一起向上递增,知道找到相同的节点,该节点就是这两个节点的最近公共祖先. 代码实现: 1 #include<cstdio> 2 #include<iostream> 3 #define N

SPOJ COT2 Count on a tree II (树上莫队,倍增算法求LCA)

题意:给一个树图,每个点的点权(比如颜色编号),m个询问,每个询问是一个区间[a,b],图中两点之间唯一路径上有多少个不同点权(即多少种颜色).n<40000,m<100000. 思路:无意中看到树上莫队,只是拿来练练,没有想到这题的难点不在于树上莫队,而是判断LCA是否在两点之间的路径上的问题.耗时1天. 树上莫队的搞法就是: (1)DFS一次,对树进行分块,分成sqrt(n)块,每个点属于一个块.并记录每个点的DFS序. (2)将m个询问区间用所属块号作为第一关键字,DFS序作为第二关键字

【树链剖分】【dfs序】【LCA】【分类讨论】Codeforces Round #425 (Div. 2) D. Misha, Grisha and Underground

一棵树,q次询问,每次给你三个点a b c,让你把它们选做s f t,问你把s到f +1后,询问f到t的和,然后可能的最大值是多少. 最无脑的想法是链剖线段树--但是会TLE. LCT一样无脑,但是少一个log,可以过. 正解是分类讨论, 如果t不在lca(s,f)的子树内,答案是dis(lca(s,f),f). 如果t在lca(s,f)的子树内,并且dep(lca(s,t))>dep(lca(f,t)),答案是dis(lca(s,t),f): 否则答案是dis(lca(f,t),f). #in

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

题意:给出 一颗树,然后q个询问,每个询问给出3个点,让我们自己选择一个起点一个终点,这条路线上的点标记,问第三个点到终点的最多标记点是多少 思路:第三个点到终点的标记点,肯定是第三个点与起点的最近公共祖先到终点的标记点.我们可以求出三个点的的三种最近公共祖先,取深度最大的点K,然后求K到三个点的距离+1 1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N=1e5+10; 4 5 const int DEG=17; 6

[CF832D] Misha, Grisha and Underground

题意:给一棵树,若指定三点(f,s,t),泽先江f到s的每一个点染色,答案为f到t路径上染色点的个数 现在给定多组询问(a,b,c),从中确定(f,s,t)使答案最大 这题考场上我居然想了出来并且1A了2333(人生第一次独立做出D绝对不是它太水) 首先让a,b,c分别作为f,取最大的答案 问题变为:已知f,s,t的位置,如何统计答案 分三类讨论(图中f为红色点,棕色路径为答案) lca(f,s)==lca(f,t) lca(f,t)==lca(s,t) lca(f,s)==lca(s,t) 然