Codeforces 1062E 题解
给出一棵有根树,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 题解的更多相关文章
- codeforces#536题解
CodeForces#536 A. Lunar New Year and Cross Counting Description: Lunar New Year is approaching, and ...
- codeforces 1093 题解
12.18 update:补充了 $ F $ 题的题解 A 题: 题目保证一定有解,就可以考虑用 $ 2 $ 和 $ 3 $ 来凑出这个数 $ n $ 如果 $ n $ 是偶数,我们用 $ n / 2 ...
- Codeforces Numbers 题解
这题只需要会10转P进制就行了. PS:答案需要约分,可以直接用c++自带函数__gcd(x,y). 洛谷网址 Codeforces网址 Code(C++): #include<bits/std ...
- Codeforces 691E题解 DP+矩阵快速幂
题面 传送门:http://codeforces.com/problemset/problem/691/E E. Xor-sequences time limit per test3 seconds ...
- Codeforces 833B 题解(DP+线段树)
题面 传送门:http://codeforces.com/problemset/problem/833/B B. The Bakery time limit per test2.5 seconds m ...
- Codeforces 840C 题解(DP+组合数学)
题面 传送门:http://codeforces.com/problemset/problem/840/C C. On the Bench time limit per test2 seconds m ...
- Codeforces 515C 题解(贪心+数论)(思维题)
题面 传送门:http://codeforces.com/problemset/problem/515/C Drazil is playing a math game with Varda. Let’ ...
- Codeforces 475D 题解(二分查找+ST表)
题面: 传送门:http://codeforces.com/problemset/problem/475/D Given a sequence of integers a1, -, an and q ...
- CodeForces CF875C题解
题解 非常有意思的\(2-SAT\)的题. 听学长讲完之后感觉确实容易想到\(2-SAT\),顺理成章. 显然,对于两个串,对咱们来说有意义的显然是两个串中第一个不同的数字.那么,我们假设两个串分别是 ...
随机推荐
- PowerShell (407) Proxy Authentication Required
$Client = New-Object -TypeName System.Net.WebClient $Client.Proxy.Credentials = [System.Net.Credenti ...
- cms-详细页面2
详细页面遗留下来的部分: 1:当前位置 2.分享 3.时间格式 4.摘要 5.关键字: 解决方案: 1:当前位置:---后台拼接 2:分享:前端一段js代码 3.摘要,直接数据库查询 4.时间格式:引 ...
- JSON.parse()与JSON.stringify()
JSON.parse() 将字符串转成JSON 举个例子 var str = '{"name":"cn","age":"2&quo ...
- Bootstrap 警告框(Alert)插件
警告消息大多来是用来向终端用户提示警告或确认的消息,使用警告框插件,您可以向所有的警告框消息添加取消功能. 用法 您有以下两种方式启用警告框的可取消功能. 1.通过data属性:通过数据添加可取消功能 ...
- 操作系统(3)_CPU调度_李善平ppt
不只上面的四种,比如时间片到了也会引起调度. 具体的调度算法: fcfs简单,但是波动很大. 最高相应比算法,执行时间最长就应该等待的长点,比sjf多了一个等待时间的考虑. 硬件定时器和软件计数器共同 ...
- 三、Shell 传递参数
Shell 传递参数 我们可以在执行 Shell 脚本时,向脚本传递参数,脚本内获取参数的格式为:$n.n 代表一个数字,1 为执行脚本的第一个参数,2 为执行脚本的第二个参数,以此类推…… 实例 以 ...
- ubuntu18.04 and Linux mint 19安装virtualbox
1.1 安装Virtualbox root@amarsoft-ZHAOYANG-K43c-:~# apt-get install virtualbox -y 1.2 显示Virtualbox桌面图 ...
- 1px移动端显示问题
设计图上的标注要有1px的线条,css本来以为直接写个1px就能万事大吉了,手机上怎么看都很粗. 至于具体为什么会这样,百度看了一圈,有点懵懵懂懂,大概就是物理分辨率高于实际网页的像素分辨率的原因吧. ...
- python标准模块
sys模块 这是一个跟python解释器关系密切的标准库.它提供了一些和python解释器操作密切的属性和函数. sys中常用的函数和属性: sys.argv: sys.argv是专门用来向pytho ...
- Java中创建(实例化)对象的五种方式
Java中创建(实例化)对象的五种方式1.用new语句创建对象,这是最常见的创建对象的方法. 2.通过工厂方法返回对象,如:String str = String.valueOf(23); 3.运用反 ...