题目

多组询问,在 \([a,b]\) 和 \([c,d]\) 中分别选一个点 \(x,y\) ,使得 \(dis(x,y)\) 最大


分析

考虑直径的一个性质,两个点集两条直径的四个端点可能成为合并后点集的直径,

用线段树维护区间直径询问时合并即可,LCA可以用dfs序 \(O(1)\) 询问


代码

#include <cstdio>
#include <cctype>
using namespace std;
const int N=100011; struct node{int y,w,next;}e[N<<1];
struct rec{int x,y;}w[N<<2];
int dep[N],dis[N],f[N<<1][18],two[18],lg[N<<1],dfn[N],as[N],n,tot,et=1;
int iut(){
int ans=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans;
}
void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
int max(int a,int b){return a>b?a:b;}
void dfs(int x,int fa){
dep[x]=dep[fa]+1,f[dfn[x]=++tot][0]=x;
for (int i=as[x];i;i=e[i].next)
if (e[i].y!=fa){
dis[e[i].y]=dis[x]+e[i].w;
dfs(e[i].y,x),f[++tot][0]=x;
}
}
int Get_Min(int x,int y){return dep[x]<dep[y]?x:y;}
int lca(int x,int y){
int l=dfn[x],r=dfn[y];
if (l>r) l^=r,r^=l,l^=r;
int z=lg[r-l+1];
return Get_Min(f[l][z],f[r-two[z]+1][z]);
}
int Dis(int x,int y){return dis[x]+dis[y]-2*dis[lca(x,y)];}
rec pup(rec A,rec B){
rec t=A; int d=Dis(A.x,A.y),now;
now=Dis(B.x,B.y); if (now>d) d=now,t=B;
now=Dis(A.x,B.x); if (now>d) d=now,t=(rec){A.x,B.x};
now=Dis(A.x,B.y); if (now>d) d=now,t=(rec){A.x,B.y};
now=Dis(A.y,B.x); if (now>d) d=now,t=(rec){A.y,B.x};
now=Dis(A.y,B.y); if (now>d) d=now,t=(rec){A.y,B.y};
return t;
}
void build(int k,int l,int r){
if (l==r){
w[k]=(rec){l,l};
return;
}
int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
w[k]=pup(w[k<<1],w[k<<1|1]);
}
rec query(int k,int l,int r,int x,int y){
if (l==x&&r==y) return w[k];
int mid=(l+r)>>1;
if (y<=mid) return query(k<<1,l,mid,x,y);
else if (x>mid) return query(k<<1|1,mid+1,r,x,y);
else return pup(query(k<<1,l,mid,x,mid),query(k<<1|1,mid+1,r,mid+1,y));
}
int main(){
n=iut(),lg[0]=-1,two[0]=1;
for (int i=1;i<18;++i) two[i]=two[i-1]<<1;
for (int i=1;i<n;++i){
int x=iut(),y=iut(),w=iut();
e[++et]=(node){y,w,as[x]},as[x]=et;
e[++et]=(node){x,w,as[y]},as[y]=et;
}
dfs(1,0);
for (int i=1;i<=tot;++i) lg[i]=lg[i>>1]+1;
for (int j=1;j<=lg[tot];++j)
for (int i=1;i+two[j]-1<=tot;++i)
f[i][j]=Get_Min(f[i][j-1],f[i+two[j-1]][j-1]);
build(1,1,n);
for (int Q=iut();Q;--Q,putchar(10)){
int lx=iut(),ly=iut(),rx=iut(),ry=iut(); rec tl=query(1,1,n,lx,ly),tr=query(1,1,n,rx,ry);
print(max(max(Dis(tl.x,tr.x),Dis(tl.x,tr.y)),max(Dis(tl.y,tr.x),Dis(tl.y,tr.y))));
}
return 0;
}

#直径,线段树#51nod 1766 树上的最远点对的更多相关文章

  1. 51nod 1766 树上的最远点对 | LCA ST表 线段树 树的直径

    51nod 1766 树上的最远点对 | LCA ST表 线段树 树的直径 题面 n个点被n-1条边连接成了一颗树,给出a~b和c~d两个区间,表示点的标号请你求出两个区间内各选一点之间的最大距离,即 ...

  2. [51nod 1766]树上的最远点对 (树的直径+ST表求lca+线段树)

    [51nod 1766]树上的最远点对 (树的直径+ST表求lca+线段树) 题面 给出一棵N个点的树,Q次询问一点编号在区间[l1,r1]内,另一点编号在区间[l2,r2]内的所有点对距离最大值.\ ...

  3. 51Nod 1766 树上的最远点对

    Description 一棵树,询问两个端点编号分别在在 \([a,b]\) 和 \([c,d]\) 两个区间中的最长链. Sol 线段树+ST表. 树上最长链可以合并,只需要合并两个区间最长链的两个 ...

  4. 51nod 1766 树上的最远点对(线段树)

    像树的直径一样,两个集合的最长路也是由两个集合内部的最长路的两个端点组成的,于是我们知道了两个集合的最长路,枚举一下两两端点算出答案就可以合并了,所以就可以用线段树维护一个区间里的最长路了. #inc ...

  5. 51nod 1766 树上的最远点对——线段树

    n个点被n-1条边连接成了一颗树,给出a~b和c~d两个区间,表示点的标号请你求出两个区间内各选一点之间的最大距离,即你需要求出max{dis(i,j) |a<=i<=b,c<=j& ...

  6. 【树形结构】51nod 1766 树上的最远点对

    题目内容 \(n\)个点被\(n−1\)条边连接成了一颗树,边有权值\(w_i\).有\(q\)个询问,给出\([a,b]\)和\([c,d]\)两个区间,表示点的标号请你求出两个区间内各选一点之间的 ...

  7. 51 nod 1766 树上的最远点对(线段树+lca)

    1766 树上的最远点对 基准时间限制:3 秒 空间限制:524288 KB 分值: 80 难度:5级算法题   n个点被n-1条边连接成了一颗树,给出a~b和c~d两个区间,表示点的标号请你求出两个 ...

  8. 51Nod.1766.树上最远点对(树的直径 RMQ 线段树/ST表)

    题目链接 \(Description\) 给定一棵树.每次询问给定\(a\sim b,c\sim d\)两个下标区间,从这两个区间中各取一个点,使得这两个点距离最远.输出最远距离. \(n,q\leq ...

  9. 【做题】51Nod1766树上的最远点对——直径&线段树

    原文链接 https://www.cnblogs.com/cly-none/p/9890837.html 题意:给出一棵大小为\(n\)的树,边有边权.\(m\)次询问,每次给出两个标号区间\([a, ...

  10. 【51nod】1766 树上的最远点对

    [题意]给定n个点的树,m次求[a,b]和[c,d]中各选出一个点的最大距离.abcd是标号区间,n,m<=10^5 [算法]LCA+树的直径理论+线段树 [题解] 树的直径性质:距离树上任意点 ...

随机推荐

  1. 2021-09-15 JavaScript中强制将某个未知类型变量转成基础数据类型

    为什么要强制将某个未知类型变量转成基础数据类型? 实际业务场景里,一个变量的数据是否合法或符合预期,会影响到自己的代码的可靠性.比如在别人使用自己写的自定义函数,而自己写的函数中的一些值是需要对入参严 ...

  2. 单继承,多继承,菱形继承---day21

    1.单继承 # ### 继承:一个类除了自身所有用的属性方法之外,还获取了另外一个类的成员属性和方法 ''' 一个类继承另外一个类,那么该类就是子类(衍生类),被继承的这个类就叫做父类(基类,超类) ...

  3. 一个简单的Dockerfile多阶段构建go项目

    From golang:1.16-alpine3.13 AS builder WORKDIR /app COPY . . RUN go build -o main main.go From alpin ...

  4. 【LeetCode二叉树#07】左叶子节点之和(基于栈的迭代法前中后序遍历复习)

    左叶子节点之和 力扣题目链接(opens new window) 计算给定二叉树的所有左叶子之和. 示例: 思路 注意审题,这里是要求 左叶子节点 之和 不是二叉树中的左侧节点之和,因此使用层序遍历是 ...

  5. 07、Etcd 中Raft算法简介

    本篇内容主要来源于自己学习的视频,如有侵权,请联系删除,谢谢. 思考: etcd是如何基于Raft来实现高可用.数据强-致性的? 1.什么是Raft算法 Raft 算法是现在分布式系统开发首选的共识算 ...

  6. Linux Cheat Sheet

  7. docker 部署prometheus和grafana

    prometheus(普罗米修斯):天生为采集存储监控数据而生的时序数据库.prometheus通过各种Exporter采集到监控数据,然后存储进prometheus中,以供查询展示. grafana ...

  8. 2022 Gartner RPA魔力象限,弘玑Cyclone位置飞跃国产RPA进击全球

    文/王吉伟 7月25日,国际权威分析机构Gartner发布了2022全球RPA魔力象限报告(Gartner RPA MQ),UiPath.Automation Anywhere.微软等来自全球的15家 ...

  9. Dash 2.16版本新特性介绍

    本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/dash-master 大家好我是费老师,几天前Dash发布了其2.16.0版本,随后在修复了一些潜在 ...

  10. Zabbix MQQT协议监控 loT设备

    一. 项目背景 监控异地局域网主机(主机内有物联5G卡 可以单方面向特定的云服务器传输信息)这里采用 zabbix 5xx系列 agent2 -6.2 版本 主动模式,即客户端向服务端注册.   二. ...