Codeforces 1062E 题解
给出一棵有根树,1为根结点,接下来q次询问,每次给出一个[l,r]区间,现在允许删掉[l,r]区间内任何一个点,使得所有点的最近公共祖先的深度尽可能大,问删掉的点是哪个点,深度最大是多少。
做法:
线段树维护区间dfs序的最大值,最小值。
首先,区间的LCA等价于区间dfs序的最小值和最大值对应的两个点的LCA。
然后,根据dfs序的性质,当删掉的点的dfs序最大或者最小时,对答案贡献最大。
所以接下来只要去查询区间里的LCA(最小值,次大值),以及LCA(次小值,最大值),两个LCA中深度最大的就是答案。
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int maxn=1e5+5; 4 #define ll long long 5 int ccnt=0; 6 int n,cnt,f[maxn],d[maxn],siz[maxn],son[maxn],rk[maxn],top[maxn],tid[maxn];//tid:dfs rk:anti-dfs 7 int d_mx; 8 struct edge 9 { 10 int to,next; 11 }e[maxn]; 12 int head[maxn]; 13 inline void addedge(int u,int v) 14 { 15 e[++ccnt].to=v; 16 e[ccnt].next=head[u]; 17 head[u]=ccnt; 18 } 19 void dfs1(int u,int fa,int depth) 20 { 21 f[u]=fa; 22 d[u]=depth; 23 d_mx=max(d_mx,d[u]); 24 siz[u]=1; 25 for(int i=head[u]; i ; i=e[i].next) 26 { 27 int v=e[i].to; 28 if(v==fa) 29 continue; 30 dfs1(v,u,depth+1); 31 siz[u]+=siz[v]; 32 if(siz[v]>siz[son[u]]) 33 son[u]=v; 34 } 35 } 36 void dfs2(int u,int t) 37 { 38 top[u]=t; 39 tid[u]=++cnt; 40 rk[cnt]=u; 41 if(!son[u]) 42 return; 43 dfs2(son[u],t); 44 for(int i=head[u]; i ; i=e[i].next) 45 { 46 int v=e[i].to; 47 if(v!=son[u]&&v!=f[u]) 48 dfs2(v,v); 49 } 50 } 51 int LCA(int x,int y) 52 { 53 if(x==y) 54 return x; 55 int fx=top[x],fy=top[y]; 56 while(fx!=fy) 57 { 58 if(d[fx]>=d[fy]) 59 { 60 x=f[fx]; 61 } 62 else 63 { 64 y=f[fy]; 65 } 66 fx=top[x]; 67 fy=top[y]; 68 } 69 if(tid[x]<=tid[y]) return x; 70 else return y; 71 } 72 #define lson o*2 73 #define rson o*2+1 74 #define m (l+r)/2 75 struct segment 76 { 77 int mx,mn; 78 }tr[4*maxn]; 79 inline void pushup(int o) 80 { 81 tr[o].mx=max(tr[lson].mx,tr[rson].mx); 82 tr[o].mn=min(tr[lson].mn,tr[rson].mn); 83 } 84 inline int ret(int o,int flag) 85 { 86 if(flag) return tr[o].mx; 87 else return tr[o].mn; 88 } 89 void build(int o,int l,int r) 90 { 91 if(l==r) 92 { 93 tr[o].mx=tr[o].mn=tid[l]; 94 return; 95 } 96 build(lson,l,m); 97 build(rson,m+1,r); 98 pushup(o); 99 } 100 int query(int o,int l,int r,int ql,int qr,int flag)//1 mx 0 mn 101 { 102 if(ql>qr) 103 { 104 if(flag) return 0; 105 else return maxn; 106 } 107 if(ql<=l&&qr>=r) 108 return ret(o,flag); 109 if(qr<=m) 110 return query(lson,l,m,ql,qr,flag); 111 if(ql>m) 112 return query(rson,m+1,r,ql,qr,flag); 113 if(flag) 114 return max(query(lson,l,m,ql,qr,flag),query(rson,m+1,r,ql,qr,flag)); 115 else 116 return min(query(lson,l,m,ql,qr,flag),query(rson,m+1,r,ql,qr,flag)); 117 } 118 int main() 119 { 120 int n,q; 121 scanf("%d%d",&n,&q); 122 for(int i=2;i<=n;i++) 123 { 124 int j; 125 scanf("%d",&j); 126 addedge(j,i); 127 } 128 dfs1(1,0,0); 129 dfs2(1,1); 130 build(1,1,n); 131 while(q--) 132 { 133 int l,r; 134 scanf("%d%d",&l,&r); 135 if(l==r) printf("%d %d\n",l,d_mx); 136 int mx=query(1,1,n,l,r,1); 137 int mn=query(1,1,n,l,r,0); 138 mx=rk[mx]; 139 mn=rk[mn]; 140 int cmx=max(query(1,1,n,l,mx-1,1),query(1,1,n,mx+1,r,1)); 141 int cmn=min(query(1,1,n,l,mn-1,0),query(1,1,n,mn+1,r,0)); 142 cmx=rk[cmx]; 143 cmn=rk[cmn]; 144 int lca1=LCA(mx,cmn); 145 int lca2=LCA(mn,cmx); 146 if(d[lca1]<d[lca2]) 147 printf("%d %d\n",mx,d[lca2]); 148 else 149 printf("%d %d\n",mn,d[lca1]); 150 } 151 }
View Code
转载于:https://www.cnblogs.com/iamamori/p/9965527.html
Codeforces 1062E 题解相关推荐
- Dominated Subarray[codeforces 1257C]题解
Dominated Subarray[codeforces 1257C] CF-1257C(Dominated Subarray) 题目 输入 输出 题目大意 样例输入 样例输出 CF-1257C(D ...
- Codeforces 833B 题解(DP+线段树)
题面 传送门:http://codeforces.com/problemset/problem/833/B B. The Bakery time limit per test2.5 seconds m ...
- Codeforces 1344 题解
A 假设所有的 \((i+a_i)\) 模 \(n\) 意义下构成排列则答案为 YES,否则为 NO. 时间复杂度 \(O(n)\) 或 \(O(n\log n)\). 代码: 79150268 B ...
- Codeforces 1314 题解
这场整体质量感觉可以算 2020 年度(目前为止)最垃圾. A 按数值从小到大扫描,维护一个优先队列,每遇到一个数加入队列,每次数值发生 \(+1\) 时弹掉队列中价值最大元素,然后把此时队列中所有元 ...
- Codeforces 1338 题解
A 对于每个 \(i\) 我们求出 \(b_i\) 表示 \(i\) 这个数最少要增加多少(\(\max^i_{j=1}a_j-a_i\)),答案等于最小的 \(k\) 使得 \(2^k-1\ge \ ...
- Codeforces 1149 题解
A 特判全是 \(2\),对于有 \(1\) 的情况把 \(1\) 放到第二个和最后. 时间复杂度 \(O(n)\). 代码: 76492031 B 考虑只有一次询问的情况,有一个 \(O(n^3)\ ...
- Codeforces 1025 题解
A 若 \(n=1\) 则答案为 YES,否则答案为 YES 当且仅当存在两个相同的字符. 时间复杂度 \(O(n)\). 代码: 76484733 B 求出所有 \(\text{lcm}(a_i,b ...
- Codeforces 1188 题解
A 首先对于 A1 题,可以加减任意实数,结论是答案为 YES 当且仅当没有度数为 \(2\) 的点.必要性显然,充分性通过下面的构造来证明. A2 题的构造:考虑随便找一个叶子节点为根,记为 \(r ...
- codeforces #1 题解
codeforces1A 题目链接:http://codeforces.com/problemset/problem/1/A 题意:给定一个n*m的矩形,然后给一个a*a的地板,求最少需要多少地板可以 ...
- Codeforces #635题解
Codeforces round 635赛后解题报告 A. Ichihime and Triangle 首先这是一道几何题 那么我们知道,在此题中, x , y , z x,y,z x,y,z 满足 ...
最新文章
- 1.0jpa 2.0_JPA 2.1类型转换器–持久枚举的更好方法
- int(a) 和 (int ) a 及 数据存储地址的探究
- 系统学习深度学习(二十一)--GoogLeNetV4与Inception-ResNet V1,V2
- 怎样使按钮响应回车键
- opencv3中camshift详解(一)camshiftdemo代码详解
- Auto.js微信抢红包脚本
- 无法启动此程序,因为计算机中丢失MSVCR71.dll.丢失的解决方法分享
- PPT中如何插入页码和母版修改
- linux 内核移植和根文件系统的制作
- CMake中cmake_minimum_required的使用
- 全连接神经网络的二分类问题
- POJ2367 家谱树
- 2021 互联网公司时薪排行榜出炉!微软、美团很强!
- ugui scrollview 3d特效 裁减
- JS-对象,包装类--渡一教育(视频笔记)
- 阿里云学生成长计划领取资格考试答案
- elk7.7.1【系列十六】java 封装 kql 查询条件
- man fputc fputs putc putchar puts
- 手把手教你用C写游程编码
- 实战SV验证学习(lab4)