给出一棵有根树,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. ASP.NET中 前后台方法的相互调用

    后台调用前台js方法: this.Page.ClientScript.RegisterStartupScript(this.GetType(), "js", "ShowM ...

  2. 【HDU4473】Exam(数学题)

    点此看题面 大致题意: 设\(f(x)=\sum[(a*b)|x]\),求\(\sum_{x=1}^nf(x)\). 转化题意 将题意进行转换,我们就可以发现,我们要求的\(ans\)就是满足\(x* ...

  3. MAC 设置登录欢迎语

    MacdeMacBook-Pro:etc mac$ cd /etc MacdeMacBook-Pro:etc mac$ cat motd 技术沉淀,空杯心态! _______ _______ _ __ ...

  4. 数组 -----JavaScript

    本文摘要:http://www.liaoxuefeng.com/ JavaScript的Array可以包含任意数据类型,并通过索引来访问每个元素.(数据里面可以有多个不同类型的元素组成) 要取得Arr ...

  5. Excel自动从身份证中提取生日、性别、年龄

    现在学生的身份证号已经全部都是18位的新一代身份证了,里面的数字都是有规律的.前6位数字是户籍所在地的代码,7-14位就是出生日期.第17位“2”代表的是性别,偶数为女性,奇数为男性.我们要做的就是把 ...

  6. sass安装更新及卸载方法

    在 Windows 平台下安装 Ruby 需要先有 Ruby 安装包,大家可以到 Ruby 的官网(http://rubyinstaller.org/downloads)下载对应需要的 Ruby 版本 ...

  7. windows下安装Linux虚拟机

    一.下载ios 下载网址:https://wwww.centos.org 选择一个.iso下载 二.安装一个vmware workstation或者Hyper-v的虚拟机 2.1.Hyper-v 2. ...

  8. java 实现猜数字游戏 随机给定一个数字,猜大小直到正确

    package com.swift; import java.util.Random; import java.util.Scanner; public class GuessBigSmall { p ...

  9. Dynemic Web Project中使用servlet的 doGet()方法接收来自浏览器客户端发送的add学生信息形成json字符串输出到浏览器并保存到本地磁盘文件

    package com.swift.servlet; import java.io.FileOutputStream;import java.io.IOException;import java.io ...

  10. PAT 乙级 1015

    题目 题目地址:PAT 乙级 1015 题解 常规题,难点在于理清楚排序规则,通过比较简洁的方式进行编码: 在这里我选择使用vector进行存储,并使用sort方法排序,因为本题不是简单按照大小排序, ...