HDU 6110 路径交(线段树+在线倍增LCA)

news/2025/1/6 4:56:27/

Description

给定一棵 n 个点的树,以及m条路径,每次询问第 L 条到第R条路径的交集部分的长度(如果一条边同时出现在 2 条路径上,那么它属于路径的交集)。

Input

第一行一个数n (n<=5105)

接下来 n1 行,每行三个数 x,y,z ,表示一条从 x y并且长度为 z 的边
n+1行一个数 m (m<=5105)

接下来 m 行,每行两个数u,v,表示一条从 u v的路径

接下来一行一个数 Q ,表示询问次数(Q<=5105)

接下来 Q 行,每行两个数L R

Output

Q行,每行一个数表示答案。

Sample Input

4
1 2 5
2 3 2
1 4 3
2
1 2
3 4
1
1 2

Sample Output

5

Solution

线段树维护路径交,树上两条路径 u1v1 u2v2 的交为 lca(u1,u2),lca(u1,v2),lca(v1,u2),lca(v1,v2) 这四个点中深度较深的两点之间的路径,在线倍增后按此合并即可, uv 路径长度即为 u 到根的长度+v到路径的长度- 2 lca(u,v) 到根的长度

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
#define maxn 500005
struct edge
{int v,w,next;
}g[2*maxn];
int tot,head[maxn];
void init()
{tot=0;memset(head,-1,sizeof(head));
}
void add(int u,int v,int w)
{g[tot].v=v,g[tot].w=w,g[tot].next=head[u],head[u]=tot++;
}
int Fa[maxn][21],Deep[maxn];
ll Dis[maxn];
void dfs(int u,int fa)
{Fa[u][0]=fa;for(int i=1;i<=20;i++)Fa[u][i]=Fa[Fa[u][i-1]][i-1];for(int i=head[u];~i;i=g[i].next){int v=g[i].v,w=g[i].w;if(v==fa)continue;Dis[v]=Dis[u]+w,Deep[v]=Deep[u]+1;dfs(v,u);}
}
int Lca(int u,int v)
{if(Deep[u]<Deep[v])swap(u,v);for(int i=20;i>=0;i--)if(Deep[Fa[u][i]]>=Deep[v])u=Fa[u][i];if(u==v)return u;for(int i=20;i>=0;i--)if(Fa[u][i]!=Fa[v][i])u=Fa[u][i],v=Fa[v][i];return Fa[u][0];
}
bool cmp(int a,int b)
{return Deep[a]>Deep[b];
}
P Unite(P x,P y)
{int a[4];a[0]=Lca(x.first,y.first),a[1]=Lca(x.first,y.second),a[2]=Lca(x.second,y.first),a[3]=Lca(x.second,y.second);sort(a,a+4,cmp);return P(a[0],a[1]);
}
#define ls (t<<1)
#define rs (t<<1|1)
P Path[maxn<<2];
void push_up(int t)
{Path[t]=Unite(Path[ls],Path[rs]);
}
void build(int l,int r,int t)
{if(l==r){scanf("%d%d",&Path[t].first,&Path[t].second);return ;}int mid=(l+r)/2;build(l,mid,ls),build(mid+1,r,rs);push_up(t);
}
P query(int L,int R,int l,int r,int t)
{if(L<=l&&r<=R)return Path[t];int mid=(l+r)/2;if(R<=mid)return query(L,R,l,mid,ls);else if(L>mid)return query(L,R,mid+1,r,rs);else return Unite(query(L,R,l,mid,ls),query(L,R,mid+1,r,rs));
}
int main()
{int n,m,q;scanf("%d",&n);init();for(int i=1;i<n;i++){int u,v,w;scanf("%d%d%d",&u,&v,&w);add(u,v,w),add(v,u,w);}dfs(1,1);scanf("%d",&m);build(1,m,1);scanf("%d",&q);while(q--){int l,r;scanf("%d%d",&l,&r);P t=query(l,r,1,m,1);int u=t.first,v=t.second;ll ans=Dis[u]+Dis[v]-2ll*Dis[Lca(u,v)];printf("%lld\n",ans); }return 0;
}

http://www.ppmy.cn/news/519719.html

相关文章

leetcode-6110:网格图中递增路径的数目

leetcode-6110&#xff1a;网格图中递增路径的数目 题目解题方法一&#xff1a;dfs记忆化搜索方法二&#xff1a;动态规划&#xff08;超时&#xff09; 题目 题目连接 给你一个 m x n 的整数网格图 grid &#xff0c;你可以从一个格子移动到 4 个方向相邻的任意一个格子。 …

华为EC6110-T_华为EC6110-M优盘刷机教程_当贝桌面纯净版

华为EC6110-T_华为EC6110-M优盘刷机教程_当贝桌面纯净版 今天小编分享一个关于华为悦盒机顶盒的救砖教程&#xff0c;最近有网友向本站求助不小心把自己的机顶盒刷错固件成砖了&#xff0c; 小编今天找到一个固件希望能帮助广大机友解决问题&#xff01; 华为EC6110-M和华为E…

hdu6110(线段树+lca)

题目 http://acm.hdu.edu.cn/showproblem.php?pid6110 分析 注意到&#xff0c;若干条路径的交一定也是条路径 我们可以维护一个线段树&#xff0c;seg[l..r]存着第l条~第r条路径的交&#xff08;用起点和终点表示即可&#xff09; 维护的时候就是两个孩子对应的路径求个交作为…

EAP(6110)作业系统launchpad之开挂做题

EAP的作业非常多&#xff0c;本文将带领你如何飞一样的直接获取Launchpad上prof布置的题目答案&#xff0c;甚至直接修改成绩&#xff01;希望同学们不要举报我提供这种“作弊”的方法。本文仅供参考学习&#xff0c;大家有时间做还是尽量自己做题吧。 方法一. 针对Exercises …

OpenSSH 安全漏洞(CVE-2019-6111) 欺骗安全漏洞(CVE-2019-6110)欺骗安全漏洞(CVE-2019-6109)解决办法

漏洞情况 如标题三个漏洞未2019年1月26日发布&#xff0c;发现存在该问题的设备使用的是OpenSSH 7.9版本。 三个安全漏洞问题为scp相关问题&#xff0c;出现在openssh-client。 解决办法: 目前发现成功解决该问题的方式是在openssh官网中找到&#xff0c;官网于4月26日发布最…

EC6110M/T-Q21A/C/E-EC6108V9/V9C/V9U/V9A/V9E/V9I/V92/V97-V9C悦me/CA全系列包

华为盒子EC6110M/T-Q21A/C/E-EC6108V9/V9C/V9U/V9A/V9E/V9I/V92/V97-V9C悦me/CA-全系列-卡刷刷机固件&#xff08;当贝桌面&#xff09; 固件说明&#xff1a; 1、采用官方系统核心以及官方内核&#xff0c;确保固件运行无问题&#xff1b; 2、全局精简&#xff0c;保留基…

EC6110M破解第一步 备份固件

前言&#xff1a;装北京移动宽带送了个电视盒子&#xff0c;型号&#xff1a;华为EC6110M。苦于家里没有电视&#xff0c;连接显示器和蓝牙音箱后声音和画面不同步&#xff0c;电视电影实在没法看&#xff0c;于是它就没有了用武之地。前一段时间在搞利用路由器搭建私有网盘&am…

OLED屏--显示问题汇总--清屏函数以及page的列地址

清屏函数&#xff1a; void Oled_Clear() { int i, j;//注意char 是 -128 -- 127&#xff0c;j会越界&#xff0c;有时会出现问题&#xff0c;unsigned char for(i0;i<8;i) { Oled_Write_Cmd(0xB0i);//page0--page7 //每个page从0列开始清…