#直径,线段树#51nod 1766 树上的最远点对
题目
多组询问,在 \([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 树上的最远点对的更多相关文章
- 51nod 1766 树上的最远点对 | LCA ST表 线段树 树的直径
51nod 1766 树上的最远点对 | LCA ST表 线段树 树的直径 题面 n个点被n-1条边连接成了一颗树,给出a~b和c~d两个区间,表示点的标号请你求出两个区间内各选一点之间的最大距离,即 ...
- [51nod 1766]树上的最远点对 (树的直径+ST表求lca+线段树)
[51nod 1766]树上的最远点对 (树的直径+ST表求lca+线段树) 题面 给出一棵N个点的树,Q次询问一点编号在区间[l1,r1]内,另一点编号在区间[l2,r2]内的所有点对距离最大值.\ ...
- 51Nod 1766 树上的最远点对
Description 一棵树,询问两个端点编号分别在在 \([a,b]\) 和 \([c,d]\) 两个区间中的最长链. Sol 线段树+ST表. 树上最长链可以合并,只需要合并两个区间最长链的两个 ...
- 51nod 1766 树上的最远点对(线段树)
像树的直径一样,两个集合的最长路也是由两个集合内部的最长路的两个端点组成的,于是我们知道了两个集合的最长路,枚举一下两两端点算出答案就可以合并了,所以就可以用线段树维护一个区间里的最长路了. #inc ...
- 51nod 1766 树上的最远点对——线段树
n个点被n-1条边连接成了一颗树,给出a~b和c~d两个区间,表示点的标号请你求出两个区间内各选一点之间的最大距离,即你需要求出max{dis(i,j) |a<=i<=b,c<=j& ...
- 【树形结构】51nod 1766 树上的最远点对
题目内容 \(n\)个点被\(n−1\)条边连接成了一颗树,边有权值\(w_i\).有\(q\)个询问,给出\([a,b]\)和\([c,d]\)两个区间,表示点的标号请你求出两个区间内各选一点之间的 ...
- 51 nod 1766 树上的最远点对(线段树+lca)
1766 树上的最远点对 基准时间限制:3 秒 空间限制:524288 KB 分值: 80 难度:5级算法题 n个点被n-1条边连接成了一颗树,给出a~b和c~d两个区间,表示点的标号请你求出两个 ...
- 51Nod.1766.树上最远点对(树的直径 RMQ 线段树/ST表)
题目链接 \(Description\) 给定一棵树.每次询问给定\(a\sim b,c\sim d\)两个下标区间,从这两个区间中各取一个点,使得这两个点距离最远.输出最远距离. \(n,q\leq ...
- 【做题】51Nod1766树上的最远点对——直径&线段树
原文链接 https://www.cnblogs.com/cly-none/p/9890837.html 题意:给出一棵大小为\(n\)的树,边有边权.\(m\)次询问,每次给出两个标号区间\([a, ...
- 【51nod】1766 树上的最远点对
[题意]给定n个点的树,m次求[a,b]和[c,d]中各选出一个点的最大距离.abcd是标号区间,n,m<=10^5 [算法]LCA+树的直径理论+线段树 [题解] 树的直径性质:距离树上任意点 ...
随机推荐
- 项目实战:C#上位机+arduino下位机+控制点亮LED灯
前言 当前比较流行的arduino开发,联动做一个Demo. 应用构架 上位机:C#上位机通过串口发送接收控制协议,来控制下位机: 下位机:arduino下位机主控,接受上位机串口协议控 ...
- 关于json序列化时报错json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
1.今天在写客户端与服务端交互的程序的时候,发现了一个问题 客户端代码 #客户端程序主要是发送注册请求/登录请求给服务端,服务端接收响应后回应对应的应答给客户端,客户端接收响应后,然后做一些操作 # ...
- djang中orm使用iterator()
当查询结果有很多对象时,QuerySet的缓存行为会导致使用大量内存.如果你需要对查询结果进行好几次循环,这种缓存是有意义的,但是对于 queryset 只循环一次的情况,缓存就没什么意义了.在这种情 ...
- 【.Net Core】.Net Core 源码分析与深入理解 - 入口 Program.cs (一)
研究原因:学习 .Net Core 两年有余,实际项目也使用了一年半,自己的技术已经到了瓶颈,需要有一个突破,我觉得首先研究架构师的设计思想,其次分析一下.Net Core的源码,这将会是一个很好的学 ...
- 【LeetCode字符串#extra】KMP巩固练习:旋转字符串、字符串轮转
旋转字符串 https://leetcode.cn/problems/rotate-string/ 给定两个字符串, s 和 goal.如果在若干次旋转操作之后,s 能变成 goal ,那么返回 tr ...
- 浅入kubernetes(3):namespace、node、pod
目前已经完成三篇关于 kubernetes 的文章: 在 Ubuntu 上安装 K8S教程 浅入kubernetes(1):Kubernetes 入门基础 浅入kubernetes(2):Kubern ...
- Java 在三个数字中找出最大值
1 int aa1 = 11000000; 2 int aa2 = 20000; 3 int aa3 = 6000; 4 5 //第一种 6 int max = (aa1 > aa2)? aa1 ...
- C++ //vector容器嵌套容器
1 //vector容器嵌套容器 2 #include <iostream> 3 #include <string> 4 #include<fstream> 5 # ...
- 计算机网络-IP地址
目录 子网划分 定长子网划分 子网划分的方法 子网掩码 可变长子网划分 无类别编址 网络前缀 路由聚合 特殊用途的IP地址 专用网络地址 链路本地地址 运营商级NAT共享地址 用于文档的测试网络地址 ...
- 【译】32位 .NET Framework 项目的 WinForm 设计器选择
在客户反馈的推动下,Visual Studio 2022 向64位架构过渡,标志着增强开发体验的关键一步.正如 Klaus Loffelmann 在他的博客文章中所描述的那样,这种转换增强了整体性能和 ...