CF1062E Company

链接

cf

luogu

题目大意

给定一颗树,有若干个询问,每个询问给出 l,r,要求编号为 ll~rr 的点任意删去一个之后剩余点的 LCA 深度最大,输出删去点的编号和 LCA 的最大深度

思路

一堆点的lca就是dfs序列的最大和最小的lca

因为只能删除一个点,那就看看删除最大的优秀还是删除最小的优秀。

修改其他的lca是不变的。查询次大线段树麻烦,主席树还能短一点。

代码

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+7;
int read() {
int x=0,f=1;char s=getchar();
for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;
for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
return x*f;
}
int n,q,a[N];
vector<int> G[N];
namespace seg {
struct node {
int ls,rs,siz,nb;
}e[N*30];
int cnt,rt[N];
void insert(int &rt,int old,int l,int r,int id,int nb) {
rt=++cnt;
e[rt]=e[old];
e[rt].siz++;
if(l==r) return e[rt].nb=nb,void();
int mid=(l+r)>>1;
if(id<=mid) insert(e[rt].ls,e[old].ls,l,mid,id,nb);
else insert(e[rt].rs,e[old].rs,mid+1,r,id,nb);
}
int k_th(int rt,int old,int l,int r,int k) {
if(l==r) return e[rt].nb;
int now=e[e[rt].ls].siz-e[e[old].ls].siz;
int mid=(l+r)>>1;
if(now>=k) return k_th(e[rt].ls,e[old].ls,l,mid,k);
else return k_th(e[rt].rs,e[old].rs,mid+1,r,k-now);
}
}
namespace diss_tree {
int dep[N],siz[N],fa[N];
int top[N],son[N],cnt;
void dfs1(int u,int f) {
a[u]=++cnt;
fa[u]=f;
siz[u]=1;
for(auto v:G[u]) {
if(f==v) continue;
dep[v]=dep[u]+1;
dfs1(v,u);
siz[u]+=siz[v];
if(siz[son[u]]<siz[v]) son[u]=v;
}
}
void dfs2(int u,int topf) {
top[u]=topf;
if(!son[u]) return;
dfs2(son[u],topf);
for(auto v:G[u])
if(!top[v]) dfs2(v,v);
}
int lca(int x,int y) {
while(top[x]!=top[y]) {
if(dep[top[x]]<dep[top[y]]) swap(x,y);
x=fa[top[x]];
}
return dep[x]<dep[y] ? x : y;
}
}
int main() {
n=read(),q=read();
for(int i=2;i<=n;++i) {
int x=read();
G[x].push_back(i);
G[i].push_back(x);
}
diss_tree::dfs1(1,0);
diss_tree::dfs2(1,1);
for(int i=1;i<=n;++i) seg::insert(seg::rt[i],seg::rt[i-1],1,n,a[i],i);
for(int i=1;i<=q;++i) {
int x=read(),y=read();
int first_max=seg::k_th(seg::rt[y],seg::rt[x-1],1,n,1);
int second_max=seg::k_th(seg::rt[y],seg::rt[x-1],1,n,2);
int first_min=seg::k_th(seg::rt[y],seg::rt[x-1],1,n,y-x+1);
int second_min=seg::k_th(seg::rt[y],seg::rt[x-1],1,n,y-x);
int tmp_x=diss_tree::dep[diss_tree::lca(first_max,second_min)];
int tmp_y=diss_tree::dep[diss_tree::lca(second_max,first_min)];
if(tmp_x > tmp_y) printf("%d %d\n",first_min,tmp_x);
else printf("%d %d\n",first_max,tmp_y);
}
return 0;
}

最新文章

  1. SQL语句总结
  2. java后端书籍推荐
  3. ASP.NET MVC 关闭 客户端 xss 检查
  4. PHP中IP地址与整型数字互相转换详解
  5. Spring MVC常用的注解类
  6. ios 获取n个月前或者n个月后的日期
  7. [原创]Devexpress XtraReports 系列 6 创建并排报表
  8. Java随机生成定长纯数字或数字字母混合数
  9. Ubuntu 14.04 64位安装Android Studio 和 genymotion (上)
  10. sql 多个字段排序,头一个字段排序完,再对第二个字段进行排序(以此类推)
  11. RabbitMQ 笔记-基本概念
  12. 构造方法里的super()方法
  13. SpringBoot Whitelabel Error Page This application has no explicit mapping for /error, so you are seeing this as a fallback.
  14. java图片缩放与裁剪
  15. Python中logging日志模块的使用
  16. day 06 元组、字典、集合的定义及其方法
  17. Unity跳转场景进度条制作教程(异步加载)
  18. Java内存模型-锁的内存语义
  19. 5289: [Hnoi2018]排列
  20. iOS - CFSocket 的使用

热门文章

  1. windows 操作系统发展过程
  2. ionic3 添加多个自定义组件
  3. python摸爬滚打之day030----进程
  4. Mac下StarUML的安装以及破解
  5. Nginx 安装后 相关错误解决
  6. nc_netcat命令
  7. Maven -- 在进行war打包时排除不需要的文件
  8. (转)jmeter接口测试--获取token
  9. python的高级数组之稀疏矩阵
  10. 递归函数 Vue ElementUI