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. Oracle诊断工具 - ORA-2730x Troubleshooting Tool

    通常情况下,ORA-27300 ORA-27301 ORA-27302错误的原因是操作系统的系统调用错误或者操作系统配置问题,错误格式:ORA-27300: OS system dependent o ...

  2. 获取INET4与INET6的信息

    获取INET4与INET6的信息 参考书籍: 本人封装的源码: // // IPAddressInfo.h // YXNETWORK // // http://www.cnblogs.com/YouX ...

  3. 使用AHKActionSheet

    使用AHKActionSheet https://github.com/fastred/AHKActionSheet 基本配置代码: AHKActionSheet *actionSheet = [[A ...

  4. Numpy 的常用操作

    1.创建数组array # 创建数组array import numpy as np a = np.array([1,2,3]) #创建数组 b = np.array([(1.5,2,3), (4,5 ...

  5. Shell中, 退出整个脚本

    常规做法 cat >test.sh<<EOF'' #!/bin/bash exit_script(){ exit 1 } echo "before exit" e ...

  6. 前端技术-HTML页面的加载

    HTML页面的加载 HTML页面的加载实际上是基于http过程+浏览器对数据的解析渲染. http协议的请求过程是基于TCP协议的.http是要基于TCP连接基础上,简单的说,TCP单纯建立连接,不涉 ...

  7. Android进阶笔记18:Android 获取Button的高度、宽度、坐标值

    1. 问题 如何获取一个控件的长和高,相信很多朋友第一眼看见这个问题都会觉得很简单,直接在onCreate里面调用getWidth.getMeasuredWidth不就可以获得了吗,但是,事实上是并没 ...

  8. 关于Koala 中文编译出错

    关于koala: 我们知道koala是一个前端预处理器语言图形编译工具,支持Less.Sass.Compass.CoffeeScript,帮助web开发者更高效地使用它们进行开发.跨平台运行,完美兼容 ...

  9. 红米5/红米5 Plus逼出最强魅蓝Note6?降价后已成性价比神机

    从品牌到产品命名,小米旗下的红米与魅族旗下的魅蓝似乎是一对天生的对手,如今小米即将发布千元全面屏的红米5/红米5 Plus,暂时没有全面屏手机推出的魅蓝也拿出了自己的应对策略,魅蓝的办法简单粗暴:直接 ...

  10. C语言程序设计I—第九周教学

    第九周教学总结(28/10-03/11) 教学内容 第三章 分支结构 3.3 查询自动售货机中商品的价格 课前准备 在蓝墨云班课发布资源: PTA:2018秋第九周作业1 3.3 分享码:530571 ...