给出一棵有根树,1为根结点,接下来q次询问,每次给出一个[l,r]区间,现在允许删掉[l,r]区间内任何一个点,使得所有点的最近公共祖先的深度尽可能大,问删掉的点是哪个点,深度最大是多少。

做法:

线段树维护区间dfs序的最大值,最小值。

首先,区间的LCA等价于区间dfs序的最小值和最大值对应的两个点的LCA。

然后,根据dfs序的性质,当删掉的点的dfs序最大或者最小时,对答案贡献最大。

所以接下来只要去查询区间里的LCA(最小值,次大值),以及LCA(次小值,最大值),两个LCA中深度最大的就是答案。

 #include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+;
#define ll long long
int ccnt=;
int n,cnt,f[maxn],d[maxn],siz[maxn],son[maxn],rk[maxn],top[maxn],tid[maxn];//tid:dfs rk:anti-dfs
int d_mx;
struct edge
{
int to,next;
}e[maxn];
int head[maxn];
inline void addedge(int u,int v)
{
e[++ccnt].to=v;
e[ccnt].next=head[u];
head[u]=ccnt;
}
void dfs1(int u,int fa,int depth)
{
f[u]=fa;
d[u]=depth;
d_mx=max(d_mx,d[u]);
siz[u]=;
for(int i=head[u]; i ; i=e[i].next)
{
int v=e[i].to;
if(v==fa)
continue;
dfs1(v,u,depth+);
siz[u]+=siz[v];
if(siz[v]>siz[son[u]])
son[u]=v;
}
}
void dfs2(int u,int t)
{
top[u]=t;
tid[u]=++cnt;
rk[cnt]=u;
if(!son[u])
return;
dfs2(son[u],t);
for(int i=head[u]; i ; i=e[i].next)
{
int v=e[i].to;
if(v!=son[u]&&v!=f[u])
dfs2(v,v);
}
}
int LCA(int x,int y)
{
if(x==y)
return x;
int fx=top[x],fy=top[y];
while(fx!=fy)
{
if(d[fx]>=d[fy])
{
x=f[fx];
}
else
{
y=f[fy];
}
fx=top[x];
fy=top[y];
}
if(tid[x]<=tid[y]) return x;
else return y;
}
#define lson o*2
#define rson o*2+1
#define m (l+r)/2
struct segment
{
int mx,mn;
}tr[*maxn];
inline void pushup(int o)
{
tr[o].mx=max(tr[lson].mx,tr[rson].mx);
tr[o].mn=min(tr[lson].mn,tr[rson].mn);
}
inline int ret(int o,int flag)
{
if(flag) return tr[o].mx;
else return tr[o].mn;
}
void build(int o,int l,int r)
{
if(l==r)
{
tr[o].mx=tr[o].mn=tid[l];
return;
}
build(lson,l,m);
build(rson,m+,r);
pushup(o);
}
int query(int o,int l,int r,int ql,int qr,int flag)//1 mx 0 mn
{
if(ql>qr)
{
if(flag) return ;
else return maxn;
}
if(ql<=l&&qr>=r)
return ret(o,flag);
if(qr<=m)
return query(lson,l,m,ql,qr,flag);
if(ql>m)
return query(rson,m+,r,ql,qr,flag);
if(flag)
return max(query(lson,l,m,ql,qr,flag),query(rson,m+,r,ql,qr,flag));
else
return min(query(lson,l,m,ql,qr,flag),query(rson,m+,r,ql,qr,flag));
}
int main()
{
int n,q;
scanf("%d%d",&n,&q);
for(int i=;i<=n;i++)
{
int j;
scanf("%d",&j);
addedge(j,i);
}
dfs1(,,);
dfs2(,);
build(,,n);
while(q--)
{
int l,r;
scanf("%d%d",&l,&r);
if(l==r) printf("%d %d\n",l,d_mx);
int mx=query(,,n,l,r,);
int mn=query(,,n,l,r,);
mx=rk[mx];
mn=rk[mn];
int cmx=max(query(,,n,l,mx-,),query(,,n,mx+,r,));
int cmn=min(query(,,n,l,mn-,),query(,,n,mn+,r,));
cmx=rk[cmx];
cmn=rk[cmn];
int lca1=LCA(mx,cmn);
int lca2=LCA(mn,cmx);
if(d[lca1]<d[lca2])
printf("%d %d\n",mx,d[lca2]);
else
printf("%d %d\n",mn,d[lca1]);
}
}

Codeforces 1062E 题解的更多相关文章

  1. codeforces#536题解

    CodeForces#536 A. Lunar New Year and Cross Counting Description: Lunar New Year is approaching, and ...

  2. codeforces 1093 题解

    12.18 update:补充了 $ F $ 题的题解 A 题: 题目保证一定有解,就可以考虑用 $ 2 $ 和 $ 3 $ 来凑出这个数 $ n $ 如果 $ n $ 是偶数,我们用 $ n / 2 ...

  3. Codeforces Numbers 题解

    这题只需要会10转P进制就行了. PS:答案需要约分,可以直接用c++自带函数__gcd(x,y). 洛谷网址 Codeforces网址 Code(C++): #include<bits/std ...

  4. Codeforces 691E题解 DP+矩阵快速幂

    题面 传送门:http://codeforces.com/problemset/problem/691/E E. Xor-sequences time limit per test3 seconds ...

  5. Codeforces 833B 题解(DP+线段树)

    题面 传送门:http://codeforces.com/problemset/problem/833/B B. The Bakery time limit per test2.5 seconds m ...

  6. Codeforces 840C 题解(DP+组合数学)

    题面 传送门:http://codeforces.com/problemset/problem/840/C C. On the Bench time limit per test2 seconds m ...

  7. Codeforces 515C 题解(贪心+数论)(思维题)

    题面 传送门:http://codeforces.com/problemset/problem/515/C Drazil is playing a math game with Varda. Let’ ...

  8. Codeforces 475D 题解(二分查找+ST表)

    题面: 传送门:http://codeforces.com/problemset/problem/475/D Given a sequence of integers a1, -, an and q ...

  9. CodeForces CF875C题解

    题解 非常有意思的\(2-SAT\)的题. 听学长讲完之后感觉确实容易想到\(2-SAT\),顺理成章. 显然,对于两个串,对咱们来说有意义的显然是两个串中第一个不同的数字.那么,我们假设两个串分别是 ...

随机推荐

  1. .net密码找回

    using System; using System.Collections.Generic; using System.Text; using System.Net.Mail; using Syst ...

  2. IOS 长按+轻扫(手势识别)

    @interface NJViewController () @property (weak, nonatomic) IBOutlet UIView *customView; @end @implem ...

  3. 【BZOJ3925】[ZJOI2015] 地震后的幻想乡(状压期望DP)

    点此看题面 大致题意: 有\(n\)个点和\(m\)条边,每条边的权值是一个\(0\sim1\)的随机实数,要你用\(n-1\)条边将图联通,问这\(n-1\)条边中边权最大值的期望最小值. 提示 这 ...

  4. Linux运维工程师是什么鬼?

    第一部分:定义 运维工程师,字面理解运行维护. linux运维即linux运维工程师,集合网络.系统.数据库.开发.安全工作于一身的“复合性人才”.   除了传统IT运维部分,运维人员还是管理制度.规 ...

  5. iOS 常用正则表达式

    今天看到一个正则表达式的文章,总结的挺好的,就自己转载一下,我还会陆续加入一些我自己看到常用的正则表达式 (原地址:http://www.code4app.com/blog-721976-112.ht ...

  6. elasticsearch RestHighLevelClient 使用方法及封装工具

    目录 EsClientRHL 更新日志 开发原因: 使用前你应该具有哪些技能 工具功能范围介绍 工具源码结构介绍 开始使用 未来规划 git地址:https://gitee.com/zxporz/ES ...

  7. SqlServer触发器的理解

    SqlServer触发器是与表事件相关的特殊存储过程,它的执行不是由程序调用,也不是手工启动,而是由事件来触发.比如当对一个表进行操作( insert,delete, update)时就会激活它执行. ...

  8. 从多个textarea中随机选取一个内容

    <div id="IMContentTest"> <textarea name="IMContent" class="IMClass ...

  9. SQL Server中Table字典数据的查询SQL示例代码

    SQL Server中Table字典数据的查询SQL示例代码 前言 在数据库系统原理与设计(第3版)教科书中这样写道: 数据库包含4类数据: 1.用户数据 2.元数据 3.索引 4.应用元数据 其中, ...

  10. 黑马基础阶段测试题:定义一个int类型的数组,数组中元素为{5,7,3,9,4}。求出数组中的最小值,并判断最小值是否为偶数,如果是偶数则输出“最小值为偶数”,如果不是偶数则输出“最小值为奇数”。打印如下:

    package com.swift; import java.util.Arrays; public class ArrayTest { public static void main(String[ ...