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. Linux 系统DNS解析原理

    DNS:域名的解析,也称A记录,CDN服务器   配置文件位置:       vi /etc/resolv.conf 解析原理 DNS就像一个倒挂的树,定点是点. www.baidu.com ==&g ...

  2. Linux head/tail命令详解

    head命令用于显示文件的开头的内容.在默认情况下,head命令显示文件的头10行内容. tail命令用于显示文件的结尾的内容.在默认情况下,taild命令显示文件的后10行内容. head常见命令参 ...

  3. Nodejs和npm入门使用

    目录 引子 何为node.js 和 npm 怎么使用node.js和npm 安装node.js & npm npm init 初始化项目(创建node.js模块) Package.json 属 ...

  4. (z转)基于CPU的Bank BRDF经验模型,实现各向异性光照效果!

    摘抄“GPU Programming And Cg Language Primer 1rd Edition” 中文 名“GPU编程与CG语言之阳春白雪下里巴人” BRDF 光照模型 10.2.1 什么 ...

  5. 一、动态网络编程的概念 二、Tomcat服务器搭建 三、Servlet组件介绍

    一.动态网络编程的概念 动态网页:结合了HTML以外的高级程序编程语言和数据库技术生成的页面. 动态网页编程技术: ASP,PHP,JSP HTTP协议:规范浏览器和服务器之间通信的数据格式. 浏览器 ...

  6. 笔记本无密码连接wifi

    用手机可以用wifi万能钥匙破解wifi,就想找电脑版的wifi万能钥匙,然并卵. 就去寻找各种办法,最后找了个巧, 用手机下载wifi万能钥匙连接,并且使用数据线连接上笔记本. 然后手机设置中找到开 ...

  7. CGI编程学习

    @CGI编程学习 目录(?)[+] 一.基本原理 CGI:通用网关接口(Common Gateway Interface)是一个Web服务器主机提供信息服务的标准接口.通过CGI接口,Web服务器就能 ...

  8. [Java123]Gradle

    https://dzone.com/articles/gradle-vs-maven https://docs.gradle.org/current/userguide/what_is_gradle. ...

  9. virtualbox+vagrant学习-2(command cli)-2-vagrant cloud命令--有问题

    Cloud https://www.vagrantup.com/docs/cli/cloud.html 命令: vagrant cloud 这是用来管理与vagrant相关的任何东西的命令. 该命令的 ...

  10. [转]托管DirectX,从MDX到SlimDX的转换

    开始迁移到托管DirectX SlimDX框架的,例如,MDX应用的帕特里克Murrisa地形的浏览器. 在托管DirectX代码所示,到新的代码,与SlimDX评论的形式. MDX迁移项目中Slim ...