E. Company

给定一颗有nnn个节点的树,有mmm次询问,每次询问给定[l,r][l, r][l,r],我们可以选择删除其中的一个点ppp,然后找到一个深度最深的rtrtrt,使得剩下的点都在rtrtrt的子树上。

考虑对编号为[l,r][l, r][l,r]中的点,按照dfsdfsdfs序排序,容易想到,我们要么删除最前面的元素,要么删除最后面的元素,

我们考虑枚举这两种情况,然后只要在剩下的点中随意挑选一个点,令其不断向上跳,知道找到一个点rtrtrt,剩下的点都在rtrtrt的子树上,这里可以通过二分处理。

考虑用线段树维护最大最小值,然后从最大最小值的点向上跳,直到找到一个点其字数上落在[l,r][l, r][l,r]的值有r−l−1r - l - 1r−l−1个,然后按照要求输出最优值即可。

#include <bits/stdc++.h>using namespace std;const int N = 1e5 + 10;int head[N], to[N], nex[N], cnt = 1;int dep[N], fa[N][20], id[N], rk[N], tot, n, m;int root[N], ls[N << 6], rs[N << 6], sum[N << 6], num;int minn[N << 2], maxn[N << 2];void add(int x, int y) {to[cnt] = y;nex[cnt] = head[x];head[x] = cnt++;
}void update(int &rt, int l, int r, int x, int v) {if (!rt) {rt = ++num;}sum[rt] += v;if (l == r) {return ;}int mid = l + r >> 1;if (x <= mid) {update(ls[rt], l, mid, x, v);}else {update(rs[rt], mid + 1, r, x, v);}
}int merge(int x, int y, int l, int r) {if (!x || !y) {return x | y;}int cur = ++num;if (l == r) {sum[cur] = sum[x] + sum[y];return cur;}int mid = l + r >> 1;ls[cur] = merge(ls[x], ls[y], l, mid);rs[cur] = merge(rs[x], rs[y], mid + 1, r);sum[cur] = sum[ls[cur]] + sum[rs[cur]];return cur;
}int query_sum(int rt, int l, int r, int L, int R) {if (l >= L && r <= R) {return sum[rt];}int ans = 0, mid = l + r >> 1;if (L <= mid) {ans += query_sum(ls[rt], l, mid, L, R);}if (R > mid) {ans += query_sum(rs[rt], mid + 1, r, L, R);}return ans;
}void dfs(int rt, int f) {fa[rt][0] = f, dep[rt] = dep[f] + 1, id[rt] = ++tot, rk[tot] = rt;for (int i = 1; i < 20; i++) {fa[rt][i] = fa[fa[rt][i - 1]][i - 1];}update(root[rt], 1, n, rt, 1);for (int i = head[rt]; i; i = nex[i]) {if (to[i] == f) {continue;}dfs(to[i], rt);root[rt] = merge(root[rt], root[to[i]], 1, n);}
}void push_up(int rt) {int ls = rt << 1, rs = rt << 1 | 1;maxn[rt] = max(maxn[ls], maxn[rs]);minn[rt] = min(minn[ls], minn[rs]);
}void build(int rt, int l, int r) {if (l == r) {maxn[rt] = minn[rt] = id[l];return ;}int mid = l + r >> 1;build(rt << 1, l, mid);build(rt << 1 | 1, mid + 1, r);push_up(rt);
}pair<int, int> merge(pair<int, int> a, pair<int, int> b) {return {min(a.first, b.first), max(a.second, b.second)};
}pair<int, int> query(int rt, int l, int r, int L, int R) {if (l >= L && r <= R) {return {minn[rt], maxn[rt]};}pair<int, int> ans = {0x3f3f3f3f, -1};int mid = l + r >> 1;if (L <= mid) {ans = merge(ans, query(rt << 1, l, mid, L, R));}if (R > mid) {ans = merge(ans, query(rt << 1 | 1, mid + 1, r, L, R));}return ans;
}int k_fa(int u, int k) {for (int i = 19; i >= 0; i--) {while (k >= (1 << i)) {u = fa[u][i], k -= 1 << i;}}return u;
}int solve(int u, int L, int R) {int l = 0, r = dep[u] - 1;while (l < r) {int mid = l + r >> 1, cur = k_fa(u, mid);if (query_sum(root[cur], 1, n, L, R) >= R - L) {r = mid;}else {l = mid + 1;}}int cur = fa[u][0];return k_fa(u, l);
}int main() {// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);scanf("%d %d", &n, &m);for (int i = 2, x; i <= n; i++) {scanf("%d", &x);add(x, i);}dfs(1, 0);build(1, 1, n);for (int i = 1, l, r; i <= m; i++) {scanf("%d %d", &l, &r);pair<int, int> cur = query(1, 1, n, l, r);int ans1 = solve(rk[cur.first], l, r), ans2 = solve(rk[cur.second], l, r);if (dep[ans1] > dep[ans2]) {printf("%d %d\n", rk[cur.second], dep[ans1] - 1);}else {printf("%d %d\n", rk[cur.first], dep[ans2] - 1);}}return 0;
}

E. Company(Codeforces Round #520 (Div. 2))相关推荐

  1. F. Bouncy Ball(Codeforces Round 859 (Div. 4))

    题目链接:Problem - F - Codeforceshttps://codeforces.com/contest/1807/problem/F 题意:给你一个n*m大小的网格,再给你一个起始点和 ...

  2. D. Boboniu Chats with Du(Codeforces Round #664 (Div. 2) )

    感受 怎么这么傻逼的题目,我现场A不了呢?看来还有不少提升的空间怎么这么傻逼的题目,我现场A不了呢?看来还有不少提升的空间怎么这么傻逼的题目,我现场A不了呢?看来还有不少提升的空间 题意 简单来说,给 ...

  3. F. Strange Array(Codeforces Round #727 (Div. 2))(主席树)

    F. Strange Array 给定一个长度为nnn的数组aaa,1≤ai≤n1 \leq a_i \leq n1≤ai​≤n,对于每个aia_iai​,我们要找到一个l≤i,r≥il \leq i ...

  4. D. Cut and Stick(Codeforces Round #716 (Div. 2))

    D. Cut and Stick 给定一个长度为nnn的数组,里面元素为a1,a2,a3,-,an−1,an,(1≤ai≤n)a_1, a_2, a_3, \dots, a_{n- 1}, a_n, ...

  5. A Perfectly Balanced String?(Codeforces Round #785 (Div. 2))

    A Perfectly Balanced String? Let's call a string s perfectly balanced if for all possible triplets ( ...

  6. Codeforces Round #777 (Div. 2) 简训

    Codeforces Round #777 (Div. 2) 简训 导语 涉及的知识点 题目 A Madoka and Math Dad B Madoka and the Elegant Gift C ...

  7. Codeforces Round #815 (Div. 2)

    Codeforces Round #815 (Div. 2) 传送门 :Codeforces Round #815 (Div. 2) 之前都是108键的键盘,最近在家用的68,两三天了还是非常不顺手, ...

  8. 「日常训练」Bad Luck Island(Codeforces Round 301 Div.2 D)

    题意与分析(CodeForces 540D) 是一道概率dp题. 不过我没把它当dp做... 我就是凭着概率的直觉写的,还好这题不算难. 这题的重点在于考虑概率:他们喜相逢的概率是多少?考虑超几何分布 ...

  9. 「日常训练」Alternative Thinking(Codeforces Round #334 Div.2 C)

    题意与分析 (CodeForces - 603A) 这题真的做的我头疼的不得了,各种构造样例去分析性质... 题意是这样的:给出01字符串.可以在这个字符串中选择一个起点和一个终点使得这个连续区间内所 ...

最新文章

  1. libIlmImf-2_2.so.22 :cannot open shared object file :No such file or direct
  2. 工作流引擎--swamp
  3. 大脑构造图与功能解析_施工技术特辑 | 全套脚手架三维构造图解析
  4. hibernate映射一对多双向关联关系实例
  5. Adapter pattern
  6. mathematica 可编辑pdf_Mathematica学习笔记[1]
  7. java护照号码校验_SpringBoot如何优雅的校验参数
  8. 调用SMS腾讯云短信验证码API的几个坑,及详细使用流程
  9. 章方:征服耶鲁教授的算法大神程序媛
  10. centos7 yum修改为国内源
  11. photoshop cs3 字体 即时预览
  12. 什么是「数独」,简单介绍
  13. photoshop的页面制作练习2
  14. JQ 对于table的动态增减
  15. xp-80c打印机无法打印_6种方法解决打印机无法打印问题
  16. 遗传算法解决作业调度c语言,遗传算法(GA)的C语言实现
  17. aardio利用鼠标钩子响应文件拖动过程(一)
  18. 1、spss中做相关分析
  19. c语言stract函数是什么,您好,这个函数该怎么办,是关于C语言strcat函数?
  20. matlab 分段函数 反余弦

热门文章

  1. 【C语言简单说】二十一:双重指针基础 (完结)
  2. python 工资管理软件_智慧职教云课堂2020Python程序设计(深圳信息职业技术学院)题目答案...
  3. 就两本书?还能吊起相扑选手?
  4. 博士毕业的人也会交“智商税”?现实远比我们想象的残酷……
  5. 这个小姐姐真的很火辣......
  6. qt4.7 mysql_详解Qt 4.7编译和访问Mysql驱动
  7. java设置窗口不可移动_Java – JDialog不可移动
  8. html二级页面内容滑动,jQuery+CSS实现的网页二级下滑菜单效果
  9. 在linux中查找运行程序句柄,如何查找我的进程在Linux中打开的文件句柄?
  10. oracle 有计划任务吗,oracle计划任务的问题