Codeforces 1062 E - Company
思路:
首先,求出每个点的dfs序
然后求一些点的公共lca, 就是求lca(u, v), 其中u是dfs序最大的点, v是dfs序最小的大点
证明: 假设o是这些点的公共lca, in[o]是o的入时间戳, out[o]是o的出时间戳,
那么对于任意一点x, in[o] <= in[v] <= in[x] <= in[u] <= out[o]
所以o是x的祖先
所以o是这些点的公共lca
所以只要求出每段区间的dfs序最大的和最小的, 删除的要么是最大的, 要么是最小的
可以删除后分成两段区间来考虑或者再求一下次大的和次小的来考虑
求次大次小可以用运算符重载写线段树, 要方便很多
代码:
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(4)
#include<bits/stdc++.h>
using namespace std;
#define fi first
#define se second
#define pi acos(-1.0)
#define LL long long
//#define mp make_pair
#define pb push_back
#define ls rt<<1, l, m
#define rs rt<<1|1, m+1, r
#define ULL unsigned LL
#define pll pair<LL, LL>
#define pli pair<LL, int>
#define pii pair<int, int>
#define piii pair<pii, int>
#define mem(a, b) memset(a, b, sizeof(a))
#define fio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define fopen freopen("in.txt", "r", stdin);freopen("out.txt", "w", stout);
//head const int N = 1e5 + ;
vector<int> g[N];
int anc[N][], deep[N], dfn[N], tot = ;
struct node {
int mx, mn, _mx, _mn;
node operator ^ (const node & rhs) {
node res = rhs;
if(dfn[mx] >= dfn[res.mx]) {
res._mx = res.mx;
res.mx = mx;
}
else if(dfn[mx] > dfn[res._mx]) {
res._mx = mx;
} if(dfn[mn] <= dfn[res.mn]) {
res._mn = res.mn;
res.mn = mn;
}
else if(dfn[mn] < dfn[res._mn]) {
res._mn = mn;
} if(dfn[_mx] >= dfn[res.mx]) {
res._mx = res.mx;
res.mx = _mx;
}
else if(dfn[_mx] > dfn[res._mx]) {
res._mx = _mx;
} if(dfn[_mn] <= dfn[res.mn]) {
res._mn = res.mn;
res.mn = _mn;
}
else if(dfn[_mn] < dfn[res._mn]) {
res._mn = _mn;
}
return res;
}
}tree[N<<];
void dfs(int u, int o) {
anc[u][] = o;
for (int i = ; i < ; i++) anc[u][i] = anc[anc[u][i-]][i-];
deep[u] = deep[o] + ;
dfn[u] = ++tot;
for (int v : g[u]) {
if(v != o) {
dfs(v, u);
}
}
}
int lca(int u, int v) {
if(deep[u] < deep[v]) swap(u, v);
for (int i = ; i >= ; i--) if(deep[anc[u][i]] >= deep[v]) u = anc[u][i];
if(u == v) return u;
for (int i = ; i >= ; i--) if(anc[u][i] != anc[v][i]) u = anc[u][i], v = anc[v][i];
return anc[u][];
}
void push_up(int rt) {
tree[rt] = tree[rt<<] ^ tree[rt<<|];
}
void build(int rt, int l, int r) {
if(l == r) {
tree[rt] = node{l, l, , };
return ;
}
int m = l+r >> ;
build(ls);
build(rs);
push_up(rt);
}
node query(int L, int R, int rt, int l, int r) {
if(L <= l && r <= R) return tree[rt];
int m = l+r >> ;
node res = {, , , };
if(L <= m) res = query(L, R, ls);
if(R > m) {
if(res.mn == ) res = query(L, R, rs);
else res = res ^ query(L, R, rs);
}
return res;
}
int main() {
int n, p, q, l, r;
scanf("%d %d", &n, &q);
for (int i = ; i <= n; i++) {
scanf("%d", &p);
g[p].pb(i);
}
dfs(, );
dfn[] = ;
build(, , n);
for (int i = ; i <= q; i++) {
scanf("%d %d", &l, &r);
node tmp = query(l, r, , , n);
int l1 = lca(tmp.mx, tmp._mn), l2 = lca(tmp._mx, tmp.mn);
// cout << tmp.mx << " " << tmp._mx << " " << tmp.mn << " " << tmp._mn << endl;
// cout << dfn[tmp.mx] << " " << dfn[tmp._mx] << " " << dfn[tmp.mn] << " " << dfn[tmp._mn] << endl;
// cout << l1 << " " << l2 << endl;
if(deep[l1] < deep[l2]) printf("%d %d\n", tmp.mx, deep[l2]-);
else printf("%d %d\n", tmp.mn, deep[l1]-);
}
return ;
}
Codeforces 1062 E - Company的更多相关文章
- Codeforces 1062 - A/B/C/D/E - (Undone)
链接:http://codeforces.com/contest/1062 A - Prank - [二分] 题意: 给出长度为 $n(1 \le n \le 100)$ 的数组 $a[1 \sim ...
- Codeforces 556D Restructuring Company
传送门 D. Restructuring Company time limit per test 2 seconds memory limit per test 256 megabytes input ...
- [刷题]Codeforces 794C - Naming Company
http://codeforces.com/contest/794/problem/C Description Oleg the client and Igor the analyst are goo ...
- CodeForces 125E MST Company
E. MST Company time limit per test 8 seconds memory limit per test 256 megabytes input standard inpu ...
- CodeForces - 794C:Naming Company(博弈&简单贪心)
Oleg the client and Igor the analyst are good friends. However, sometimes they argue over little thi ...
- CodeForces - 566D Restructuring Company 并查集的区间合并
Restructuring Company Even the most successful company can go through a crisis period when you have ...
- CODEFORCES 125E MST Company 巧用Kruskal算法
题意:给定一个带权边无向图,求最小生成树,且满足第一个节点的度为固定的k 无解则输出-1 数据规模: 节点数n和限制k<=5000 边数m<=10^5 时限8sec 思路: 首先时限比较宽 ...
- CodeForces 566D Restructuring Company (并查集+链表)
题意:给定 3 种操作, 第一种 1 u v 把 u 和 v 合并 第二种 2 l r 把 l - r 这一段区间合并 第三种 3 u v 判断 u 和 v 是不是在同一集合中. 析:很容易知道是用并 ...
- 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 ...
随机推荐
- Yii1使用Gii生成模块实现CURD
Yii里Gii的强大就不用说了,可以快速生成模块的Model.Controller来开发.要使用Gii,首先你需要创建好操作的数据表. 第一步:创建数据表 CREATE TABLE `t_knowle ...
- Linux共享内存的管理
在进程通信应用中会用到共享内存,这就涉及到了IPC,与IPC相关的命令包括:ipcs.ipcrm(释放IPC).IPCS命令是Linux下显示进程间通信设施状态的工具.我们知道,系统进行进程间通信(I ...
- 教你用Visual Studio Code做PHP开发 - 微软官方工具,IDE中的黑马
转载于:http://bbs.wfun.com/thread-902655-1-1.html,仅供自己备忘 本文为我在智机网的原创 ] 关于Visual Studio Code,可能有的开发者很陌生 ...
- Codeforces 675E Trains and Statistic - 线段树 - 动态规划
题目传送门 快速的vjudge通道 快速的Codeforces通道 题目大意 有$n$个火车站,第$i$个火车站出售第$i + 1$到第$a_{i}$个火车站的车票,特殊地,第$n$个火车站不出售车票 ...
- 字体图标,盒子显隐,overflow属性,伪类设计边框,盒子阴影2d形变
字体图标 ''' fa框架: http://fontawesome.dashgame.com/ 下载 => 引入css文件 引入字体图标库 <link rel="styleshe ...
- onsaveInstanceState有关问题
在学习活动回收时,遇到当活动回收时开始在onresume状态的活动转为onpause时,活动的数据可能会丢失(取决于手机内存)只有在这时onsaveInstanceState方法才会有用武之地,这个方 ...
- Web Service平台有三种元素构成:SOAP、WSDL、UDDI。区别和联系
Web Service平台有三种元素构成:SOAP.WSDL.UDDI.一个消费者可以在UDDI注册表查找服务,取得服务的WSDL描述,然后通过SOAP来调用服务.SOAP.WSDL.UDDI的区别如 ...
- linux内核中侧async_tx是什么?
答: 异步内存传输api(asynchronous memory transfer/transform API),这是一种api,用来为应用提供操作DMA的API. 下图是async_tx在架构中所处 ...
- bsgs整理
目录 bsgs问题 或 poj2417: 概述 代码 exbsgs 鸣谢 \(gzy gzy gzy\) bsgs问题 或 poj2417: 给定质数\(p\),给定\(a\),\(b\),\((a, ...
- P3980 [NOI2008]志愿者招募
思路 巧妙的建图 因为每个志愿者有工作的时段,所以考虑让一个志愿者的流量能够从S流到T产生贡献 所以每个i向i+1连INF-a[x]的边(类似于k可重区间集),每个si向ti连边cap=INF,cos ...