[CF1062E] Company
Posted alecli
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[CF1062E] Company相关的知识,希望对你有一定的参考价值。
题意
思考
最重要的问题在于,我们删去哪个点后,剩下点的公共 (LCA) 深度最大,即如何确定这个点。我们感性的观察和理性的分析之后,发现和点的 (dfn) 序有关系,要么删去当前区间点 (dfn) 最大的,要么删最小的。
如果得出上面那个结论就好办了,拿个线段树维护区间 (dfn) 的最大和最小值,选择是删 (dfn) 最大的点还是最小的点即可。
代码
#include<bits/stdc++.h>
#define ls(pos) pos << 1
#define rs(pos) pos << 1 | 1
using namespace std;
const int N = 100010;
const int M = 100010;
struct node{
int nxt, to;
}edge[M << 1];
int head[N], num;
void build(int from, int to){
edge[++num].nxt = head[from];
edge[num].to = to;
head[from] = num;
}
int dfn[N], cnt, f[N][20], rev[N], d[N], n, q;
namespace Seg{
int Max[N << 2], Min[N << 2];
void pushup(int pos){
Max[pos] = max( Max[ls(pos)], Max[rs(pos)] );
Min[pos] = min( Min[ls(pos)], Min[rs(pos)] );
}
void build(int pos, int l, int r){
if(l == r){
Max[pos] = Min[pos] = dfn[l];
return;
}
int mid = (l + r) >> 1;
build(ls(pos), l, mid);
build(rs(pos), mid+1, r);
pushup(pos);
}
void modify(int pos, int l, int r, int x, int v){
if(l == r && l == x){
Max[pos] = max(Max[pos], v);
Min[pos] = min(Min[pos], v);
return;
}
int mid = (l + r) >> 1;
if(x <= mid) modify(ls(pos), l, mid, x, v);
else modify(rs(pos), mid+1, r, x, v);
pushup(pos);
}
int QMAX(int pos, int l, int r, int x, int y){
int ans = 0;
if(l > y || r < x) return 0;
if(x <= l && r <= y) return Max[pos];
int mid = (l + r) >> 1;
if(x <= mid) ans = max(ans, QMAX(ls(pos), l, mid, x, y));
if(y > mid) ans = max(ans, QMAX(rs(pos), mid+1, r, x, y));
return ans;
}
int QMIN(int pos, int l, int r, int x, int y){
int ans = 0x3f3f3f3f;
if(l > y || r < x) return 0x3f3f3f3f;
if(x <= l && r <= y) return Min[pos];
int mid = (l + r) >> 1;
if(x <= mid) ans = min(ans, QMIN(ls(pos), l, mid, x, y));
if(y > mid) ans = min(ans, QMIN(rs(pos), mid+1, r, x, y));
return ans;
}
}
using namespace Seg;
void dfs(int u, int fa){
dfn[u] = ++cnt; rev[cnt] = u;
for(int i=head[u]; i; i=edge[i].nxt){
int v = edge[i].to;
if(v == fa) continue;
d[v] = d[u] + 1;
f[v][0] = u;
dfs(v, u);
}
}
int lca(int u, int v){
if(d[u] < d[v]) swap(u, v);
for(int i=18; i>=0; i--) if(d[f[u][i]] >= d[v]) u = f[u][i];
if(u == v) return u;
for(int i=18; i>=0; i--) if(f[u][i] != f[v][i]) u = f[u][i], v = f[v][i];
return f[u][0];
}
int main(){
cin >> n >> q;
for(int i=2; i<=n; i++){
int v; cin >> v;
build(i, v); build(v, i);
}
d[1] = 1;
dfs(1, 0);
build(1, 1, n);
for(int j=1; j<=18; j++)
for(int i=1; i<=n; i++) f[i][j] = f[f[i][j-1]][j-1];
while(q --){
int l, r, L, Lu, R, Ru, L2, L2u, R2, R2u, LCA1, LCA2;
int flag = 0;
cin >> l >> r;
L = QMIN(1, 1, n, l, r), R = QMAX(1, 1, n, l, r);
Lu = rev[L], Ru = rev[R];
L2 = min(QMIN(1, 1, n, l, Lu - 1), QMIN(1, 1, n, Lu + 1, r));
R2 = max(QMAX(1, 1, n, l, Ru - 1), QMAX(1, 1, n, Ru + 1, r));
L2u = rev[L2], R2u = rev[R2];
LCA1 = lca(Lu, R2u); LCA2 = lca(L2u, Ru);
if(d[LCA1] > d[LCA2]) flag = 1;
else flag = 0;
if(flag){
cout << Ru << " " << d[LCA1] - 1 << endl;
}
else cout << Lu << " " << d[LCA2] - 1 << endl;
}
return 0;
}
总结
大概猜出第一个结论就好做了。
以上是关于[CF1062E] Company的主要内容,如果未能解决你的问题,请参考以下文章