Description

The company \(X\) has \(n\) employees numbered from \(1\) through \(n\). Each employee \(u\) has a direct boss \(p_u\) \((1 \le p_u \le n)\), except for the employee \(1\) who has no boss. It is guaranteed, that values \(p_i\) form a tree. Employee \(u\) is said to be in charge of employee \(v\) if \(u\) is the direct boss of \(v\) or there is an employee \(w\) such that \(w\) is in charge of \(v\) and \(u\) is the direct boss of \(w\). Also, any employee is considered to be in charge of himself.

In addition, for each employee \(u\) we define it's level \(lv(u)\) as follow:

  • \(lv(1)=0\)
  • \(lv(u)=lv(p_u)+1\) for \(u \neq 1\)

In the near future, there are \(q\) possible plans for the company to operate. The \(i\)-th plan consists of two integers \(l_i\) and \(r_i\), meaning that all the employees in the range \([l_i,r_i]\), and only they, are involved in this plan. To operate the plan smoothly, there must be a project manager who is an employee in charge of all the involved employees. To be precise, if an employee \(u\) is chosen as the project manager for the \(i\)-th plan then for every employee \(v \in [l_i,r_i]\), \(u\) must be in charge of \(v\). Note, that \(u\) is not necessary in the range \([l_i,r_i]\). Also, \(u\) is always chosen in such a way that \(lv(u)\) is as large as possible (the higher the level is, the lower the salary that the company has to pay the employee).

Before any plan is operated, the company has JATC take a look at their plans. After a glance, he tells the company that for every plan, it's possible to reduce the number of the involved employees exactly by one without affecting the plan. Being greedy, the company asks JATC which employee they should kick out of the plan so that the level of the project manager required is as large as possible. JATC has already figured out the answer and challenges you to do the same.

Input

The first line contains two integers \(n\) and \(q\) \((2 \le n \le 100000, 1 \le q \le 100000)\) — the number of employees and the number of plans, respectively.

The second line contains \(n−1\) integers \(p_2,p_3,…,p_n(1≤p_i≤n)\) meaning \(p_{i}\) is the direct boss of employee \(i\).

It is guaranteed, that values \(p_{i}\) form a directed tree with the root of \(1\).

Each of the following \(q\) lines contains two integers \(l_i\) and \(r_i\) \((1 \le l_i < r_i \le n)\) — the range of the employees, involved in the corresponding plan.

Output

Print \(q\) lines, each containing two integers — the number of the employee which should be kicked from the corresponding plan and the maximum possible level of the project manager in that case.

If there are more than one way to choose that employee, print any of them.

Example

Input

11 5
1 1 3 3 3 4 2 7 7 6
4 6
4 8
1 11
9 11
8 11

Output

4 1
8 1
1 0
11 3
8 1

Note

In the example:

In the first query, we can choose whether \(4\) or \(5\) or \(6\) and the project manager will be \(3\).

In the second query, if we choose any employee other than the employee \(8\), the project manager will be \(1\). If we choose \(8\), the project manager will be \(3\). Since \(lv(3)=1 \gt lv(1)=0\), choosing \(8\) is the best strategy.

In the third query, no matter how we choose the employee, the project manager will always be \(1\).

In the fourth query, if we choose \(9\) or \(10\) then the project manager will be \(3\). If we choose \(11\) then the project manager will be \(7\). Since \(lv(7)=3 \gt lv(3)=1\), we choose \(11\) as the answer.

Solution

题意:给一棵树,\(n\)个点,\(q\)次询问,每次询问给定一个区间\([l, r]\),要求忽略掉\([l, r]\)中的一个点,使得剩下的$r - l $个点的LCA的深度最大,问应该忽略哪个点,忽略后的最大深度是多少。

首先求一次DFS序,对于任意点\(u\),其DFS序记为\(order[u]\)。给定区间\([l, r]\),设其中DFS序最大和最小的点分别为\(u\)和\(v\),则\(LCA[l, r]\)就是\(LCA(u, v)\)。我们可以简单证明一下,不妨设\(r = LCA(u, v)\),点\(x\)不属于以\(r\)为根的子树(记作\(SubTree(r)\))当且仅当\(order[x]\)满足以下两种情况中的一种:

  • \(order[x] \lt order[r]​\),即\(x​\)在\(r​\)之前被访问
  • \(order[x] > order[i], \forall i \in SubTree(r)\),即\(x\)在\(SubTree(r)\)之后才被访问

显然,\([l, r]\)中的任何一个点都不满足上述两个条件,所以\([l, r]\)中的每个点都属于以\(r\)为根的子树,所以它们的LCA就是\(r\)。

回到我们的问题,对于每次询问,给定\([l, r]\),我们先求出其中DFS序最大、最小的点\(u, v\)以及它们的LCA \(r\)。显然,忽略\(u\)和\(v\)之外的节点对并不会改变LCA;如果忽略\(u\),那么新的LCA就是\(LCA[l, u-1]\)和\(LCA[u + 1, r]\)的LCA,我们称之为\(r_1\);同理,忽略\(v\)也可以得到一个新的LCA,我们称之为\(r_2\)。选择\(r, r_1, r_2\)中深度最大的点,我们就得到了答案。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 100011;
const int maxp = 18;
vector<int> w[maxn];
int idx, dfsod[maxn], invdfsod[maxn];
int fa[maxn][maxp], dep[maxn];
void bfs(int root) {
queue<int> que;
dep[root] = 0;
fa[root][0] = root;
que.push(root);
while (!que.empty()) {
int u = que.front();
que.pop();
for (int i = 1; i < maxp; i++)
fa[u][i] = fa[fa[u][i - 1]][i - 1];
for (int v : w[u]) {
if (v == fa[u][0]) continue;
dep[v] = dep[u] + 1;
fa[v][0] = u;
que.push(v);
}
}
}
int lca(int u, int v) {
if (dep[u] > dep[v])
swap(u, v);
for (int gap = dep[v] - dep[u], i = 0; gap; gap >>= 1, i++) {
if (gap & 1)
v = fa[v][i];
}
if (u == v) return u;
for (int i = maxp - 1; i >= 0; i--) {
if (fa[u][i] == fa[v][i])
continue;
u = fa[u][i], v = fa[v][i];
}
return fa[u][0];
}
void dfs(int u, int pre = -1) {
dfsod[u] = ++idx;
invdfsod[idx] = u;
for (int v : w[u]) {
if (v == pre) continue;
dfs(v, u);
}
}
struct node {
int l, r, mx, mn;
} seg[maxn << 2];
void pushup(int x) {
seg[x].mx = max(seg[x << 1].mx, seg[x << 1 | 1].mx);
seg[x].mn = min(seg[x << 1].mn, seg[x << 1 | 1].mn);
}
void build(int x, int l, int r) {
seg[x].l = l, seg[x].r = r;
if (l == r) {
seg[x].mx = seg[x].mn = dfsod[l];
return;
}
int m = (l + r) >> 1;
build(x << 1, l, m);
build(x << 1 | 1, m + 1, r);
pushup(x);
}
pair<int, int> query(int x, int l, int r) {
int L = seg[x].l, R = seg[x].r;
if (l <= L && r >= R)
return make_pair(seg[x].mn, seg[x].mx);
int m = (L + R) >> 1;
int mx = 0, mn = 1 << 30;
if (l <= m) {
auto v = query(x << 1, l, r);
mn = min(mn, v.first);
mx = max(mx, v.second);
}
if (r > m) {
auto v = query(x << 1 | 1, l, r);
mn = min(mn, v.first);
mx = max(mx, v.second);
}
return make_pair(mn, mx);
}
// 区间[l, r]的LCA
int getlca(int l, int r) {
if (l > r) return -1;
auto x = query(1, l, r);
int u = invdfsod[x.first], v = invdfsod[x.second];
return lca(u, v);
}
// 忽略u后,区间[l, r]的LCA
int getlca(int l, int r, int u) {
int a = getlca(l, u - 1), b = getlca(u + 1, r);
if (a == -1) return b;
if (b == -1) return a;
return lca(a, b);
}
int main() {
int n, q;
scanf("%d%d", &n, &q);
for (int i = 2; i <= n; ++i) {
int x; scanf("%d", &x);
w[x].push_back(i);
w[i].push_back(x);
}
bfs(1);
dfs(1);
build(1, 1, n);
dep[0] = -1;
while (q--) {
int l, r;
scanf("%d%d", &l, &r);
auto x = query(1, l, r);
int u = invdfsod[x.first], v = invdfsod[x.second];
int c = lca(u, v), a = getlca(l, r, u), b = getlca(l, r, v);
int mx = max(dep[c], max(dep[a], dep[b])), y;
if (mx == dep[c]) y = l;
else if (mx == dep[a]) y = u;
else y = v;
printf("%d %d\n", y, mx);
}
return 0;
}

CodeForces 1062E Company的更多相关文章

  1. Codeforces 1090A - Company Merging - [签到水题][2018-2019 Russia Open High School Programming Contest Problem A]

    题目链接:https://codeforces.com/contest/1090/problem/A A conglomerate consists of n companies. To make m ...

  2. Codeforces 1062E 题解

    给出一棵有根树,1为根结点,接下来q次询问,每次给出一个[l,r]区间,现在允许删掉[l,r]区间内任何一个点,使得所有点的最近公共祖先的深度尽可能大,问删掉的点是哪个点,深度最大是多少. 做法: 线 ...

  3. CodeForces 1025G Company Acquisitions

    题意 描述有点麻烦,就不写了. \(\texttt{Data Range:}1\leq n\leq 500\) 题解 势能函数这个东西好神啊-- 这个题目用常规的 DP 好像做不出来,所以我们可以考虑 ...

  4. Codeforces 556D Restructuring Company

    传送门 D. Restructuring Company time limit per test 2 seconds memory limit per test 256 megabytes input ...

  5. Codeforces Round #321 (Div. 2) B. Kefa and Company 二分

    B. Kefa and Company Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/580/pr ...

  6. [刷题]Codeforces 794C - Naming Company

    http://codeforces.com/contest/794/problem/C Description Oleg the client and Igor the analyst are goo ...

  7. CodeForces 125E MST Company

    E. MST Company time limit per test 8 seconds memory limit per test 256 megabytes input standard inpu ...

  8. Codeforces 1062 E - Company

    E - Company 思路: 首先,求出每个点的dfs序 然后求一些点的公共lca, 就是求lca(u, v), 其中u是dfs序最大的点, v是dfs序最小的大点 证明: 假设o是这些点的公共lc ...

  9. Codeforces Round #520 (Div. 2) E. Company(dfs序判断v是否在u的子树里+lca+线段树)

    https://codeforces.com/contest/1062/problem/E 题意 给一颗树n,然后q个询问,询问编号l~r的点,假设可以删除一个点,使得他们的最近公共祖先深度最大.每次 ...

随机推荐

  1. 定制NSError

    定制NSError 效果: 系统的NSError是可以自己定制的,以下提供代码来实现并表示如何使用: YXError.h 与 YXError.m // // YXError.h // CustomYX ...

  2. 重置 Winsock:初始化计算机网络环境

    初始化网络环境,以解决由于软件冲突.病毒原因造成的参数错误问题(复杂网络环境下慎用).批处理代码: netsh winhttp reset proxy netsh winhttp reset trac ...

  3. centos6 安装glibc-2.14.1

    CentOS默认的glibc版本为2.12.1, 网上都是给出的升级至glibc-2.14.1的方法, 都是用glibc-2.14.1.tar.gz [root@192-168-0-151 ~]# s ...

  4. DSU on Tree浅谈

    DSU on tree 在之前的一次比赛中,学长向我们讲了了这样一个神奇的思想:DSU on tree(树上启发式合并),看上去就非常厉害--但实际上是非常暴力的一种做法;不过暴力只是看上去暴力,它在 ...

  5. Guava包学习--Hash

    我们HashMap会有一个rehash的过程,为什么呢?因为java内建的散列码被限制为32位,而且没有分离散列算法和所作用的数据,所以替代算法比较难做.我们使用HashMap的时候它自身有一个reh ...

  6. C语言利用 void 类型指针实现面向对象类概念与抽象。

    不使用C++时,很多C语言新手可能认为C语言缺乏了面向对象和抽象性,事实上,C语言通过某种组合方式,可以间接性的实现面对对象和抽象. 不过多态和继承这种实现,就有点小麻烦,但是依然可以实现. 核心: ...

  7. ali验证码推送接口调用

    /** * 发送接口 * @param $info 发送信息的某些参数 * @return bool */ public function send($info) { $config = target ...

  8. python 二维数组键盘输入

    m = int(input()) grid = [[] for i in range(m)] for i in range(m): line = input().split(' ') for j in ...

  9. Sql Server 数据库扩展

    1. 查询一个表的所有列名 ------查询一个表的所有列名 Select Name FROM SysColumns Where id=Object_Id('Sys_User') select t.c ...

  10. Django输入 中文参数保存异常解决方法

    WEB页面输入中文后保存,出现异常     cmd.exe打印如下信息: UnicodeEncodeError: 'ascii' codec can't encode characters in po ...