hdu 6010 路径交(lca + 线段树)

题意:

给出一棵大小为\(n\)的树和\(m\)条路径,求第\(L\)条路径到第\(R\)条路径的交的路径的长度

思路:

本题的关键就是求路径交

假设存在两条路径(a,b),(c,d),那它们的交是怎样的呢

画图看看,分三种情况

  • 1、路径不存在交集
  • 2、(c,d)交(a,b)路径的一边(由lca(a,b)将路径划分成两部分,假设这里交在a的一侧)
  • 3、(c,d)交(a,b)路径的两边

可以看出路径交若存在,这其两端点一定在lca(a,c),lca(a,d),lca(b,c),lca(b,d)中取到,

而且是取深度最大的两点,如果这两点相同,那么显然路径只交于一点了

这里是问边的交集

如果是求的点的交集,还需要判断一下点是否在路径上,可以用距离来判断

然后剩下的来就是简单的线段树求区间的合并了

#include<bits/stdc++.h>
#define LL long long
#define P pair<int,int>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define ls rt<<1
#define rs (rt<<1|1)
using namespace std;
int read(){
int x = 0;
char c = getchar();
while(c < '0' || c > '9') c = getchar();
while(c >= '0' && c <= '9') x = x * 10 + c - 48, c = getchar();
return x;
}
const int N = 5e5 + 10;
int n,m;
int pre[N];
vector<P> G[N];
int dep[N],dis[N];
int fa[N][25];
int dp[N][25];
int ver[2 * N],tot;
int first[N],R[2 * N];
void dfs(int u,int f,int d,int dw){
dep[u] = d;
dis[u] = dw;
fa[u][0] = f;
ver[++tot] = u;
first[u] = tot,R[tot] = d;
// for(int i = 1;i <= 20;i++) fa[u][i] = fa[fa[u][i-1]][i-1];
for(int i = 0;i < G[u].size();i++){
if(G[u][i].first != f) {
dfs(G[u][i].first,u,d + 1,dw + G[u][i].second);
ver[++tot] = u;
R[tot] = d;
}
}
}
void ST(int n){
for(int i = 1;i <= n;i++) dp[i][0] = i;
for(int j = 1;(1<<j)<=n;j++){
for(int i = 1;i + (1<<j) - 1 <= n;i++){
int a= dp[i][j-1],b = dp[i+(1<<(j-1))][j-1];
dp[i][j] = R[a] < R[b]?a:b;
}
}
}
int RMQ(int l,int r){
int k = pre[r - l + 1];
int a = dp[l][k],b = dp[r-(1<<k)+1][k];
return R[a] < R[b]?a:b;
}
int lca(int u,int v){
int x = first[u],y = first[v];
if(x > y) swap(x,y);
int res = RMQ(x,y);
return ver[res];
}/*
int lca(int u,int v){
if(dep[u] < dep[v]) swap(u,v);
int d = dep[u] - dep[v];
for(int i = 20;i >= 0 && u != v;i--) if(d & (1<<i)) 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];
}*/
int getdis(int u,int v){
return dis[u] + dis[v] - 2 * dis[lca(u,v)];
}
void sw(int &x,int &y){
if(dep[x] < dep[y]) swap(x,y);
}
struct Line{
int u,v,uv;
Line(int u,int v,int uv):u(u),v(v),uv(uv){};
Line(){};
Line operator+(const Line &rhs)const{
if(uv == 0) return rhs;
if(rhs.uv == 0)return *this;
if(uv == -1 || rhs.uv == -1) return Line(0,0,-1);
Line ans;
int lu = lca(u,rhs.u), lv = lca(u,rhs.v);
int ru = lca(v,rhs.u), rv = lca(v,rhs.v);
sw(lu,lv);sw(ru,rv);
if(dep[lu] > dep[ru]){
ans.u = lu;
ans.v = dep[ru] > dep[lv]?ru:lv;
}else {
ans.u = ru;
ans.v = dep[lu] > dep[rv]?lu:rv;
}
if(ans.u == ans.v) return Line(0,0,-1);
ans.uv = lca(ans.u,ans.v);
return ans;
}
}s[N << 2];
void build(int l,int r,int rt){
if(l == r){
s[rt].u = read();
s[rt].v = read();
s[rt].uv = lca(s[rt].u,s[rt].v);
return ;
}
int m = (l + r)>>1;
build(l,m,rt<<1);
build(m+1,r,rt<<1|1);
s[rt] = s[rt<<1] + s[rt<<1|1];
}
Line query(int L,int R,int l,int r,int rt){
if(L <= l && R >= r) return s[rt];
int m = l + r >>1;
Line ans = Line(0,0,0);
if(L <= m) ans = ans + query(L,R,l,m,rt<<1);
if(R > m) ans = ans + query(L,R,m+1,r,rt<<1|1);
return ans;
}
int main(){
for(int i = 1;i < N ;i++) pre[i] = log2(i);
int u,v,w;
while(scanf("%d",&n)==1){
for(int i = 1;i < n;i++){
u = read(),v = read(), w = read();
G[u].push_back(P(v,w));
G[v].push_back(P(u,w));
}
dfs(1,-1,0,0);
ST(2 * n - 1);
int m = read();
build(1,m,1);
int q = read(),L,R;
while(q--){
L = read(),R = read();
Line ans = query(L,R,1,m,1);
if(ans.uv == -1) printf("%d\n",0);
else printf("%d\n",dis[ans.u] + dis[ans.v] - dis[ans.uv] * 2);
}
}
return 0;
}

hdu 6010 路径交的更多相关文章

  1. 2017"百度之星"程序设计大赛 - 初赛(A) [ hdu 6108 小C的倍数问题 ] [ hdu 6109 数据分割 ] [ hdu 6110 路径交 ] [ hdu 6112 今夕何夕 ] [ hdu 6113 度度熊的01世界 ]

    这套题体验极差. PROBLEM 1001 - 小C的倍数问题 题 OvO http://acm.hdu.edu.cn/showproblem.php?pid=6108 (2017"百度之星 ...

  2. hdu 5700区间交(线段树)

    区间交 Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submiss ...

  3. hihocoder[Offer收割]编程练习赛19 D 相交的铁路线(树上路径交)

    傻逼题... 裸的树上路径交 两条树上的路径$[a,b]$和$[c,d]$有交,则有$lca(a,b)$在$[c,d]$上或$lca(c,d)$在$[a,b]$上. 其实只要深度大的$lca$在另一条 ...

  4. 【百度之星初赛A】路径交 LCA+线段树

    [百度之星初赛A]路径交 Problem Description 给定一棵n个点的树,以及m条路径,每次询问第L条到第R条路径的交集部分的长度(如果一条边同时出现在2条路径上,那么它属于路径的交集). ...

  5. hdu6110:路径交

    $n \leq 500000$的树给$m \leq 500000$个路径,$q \leq 500000$个询问每次问一个区间的路径交. 路径交口诀:(前方高能) 判有交,此链有彼祖: 取其交,最深两两 ...

  6. HDU 6116 路径计数

    HDU 6116 路径计数 普通生成函数常用于处理组合问题,指数生成函数常用于处理排列问题. 考虑 对于 $ a $ 个 $ A $ 分为很多堆,这么分的方案数是 $ C_{a-1}^{i-1} $ ...

  7. 【HDU】6110 路径交(2017百度之星) 线段树+RMQ-LCA+树链的交

    [题目]2017"百度之星"程序设计大赛 - 初赛(A) [题意]给定n个点的带边权树,m条编号1~m的路径,Q次询问编号区间[L,R]所有链的交集的长度.n<=500000 ...

  8. HDU 5700 区间交(线段树)

    [题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5700 [题目大意] 给出一个长度为n的数列和m个区间,现在求k个区间,使得他们的区间交内的数列项和 ...

  9. HDU 5700 区间交 离线线段树

    区间交 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=5700 Description 小A有一个含有n个非负整数的数列与m个区间.每个区间可以表示为 ...

随机推荐

  1. Map the Debris -freecodecamp算法题目

    Map the Debris 1.要求 返回一个数组,其内容是把原数组中对应元素的平均海拔转换成其对应的轨道周期. 原数组中会包含格式化的对象内容,像这样 {name: 'name', avgAlt: ...

  2. C#基础学习笔记(个人整理)

    学习笔记 第一章:c#基础 一.程序设计语言的发展及历史 1.程序设计语言? 通俗也叫编程语言,实现人与机器交互的工具 2.历史 1)机器语言 : 0,1 2)汇编语言 : 包含一些机器语言,同时增加 ...

  3. 解决 div或者a标签的高度比里面的img高度多的 问题

    今天做练习遇到一个问题,分享一下解决办法: 在编写html中的一个放置图片时,代码如下: <div class="nrtp"> <div class=" ...

  4. Python类与对象--基础

    ## 类 - 具体事物的抽象和总结,是事物的共性,由属性和方法两个部分构成,比如一个Person类,有是身高.体重.肤色等属性,也有吃饭.睡觉.观察.等方法 ## 对象 - 具体的事物,单一.个体.特 ...

  5. Centos7安装Mysql5.7并修改初始密码

    1.CentOS 的yum源中没有mysql,需要到mysql的官网下载yum repo配置文件. wget https://dev.mysql.com/get/mysql57-community-r ...

  6. <Docker学习>3. docker镜像命令使用

    镜像提供容器运行时所需要的程序,资源.配置文件等,是一个特殊的文件系统.是容器运行的基础.镜像是多层文件系统组成的,是一个分层存储的架构,在镜像的构建中,会一层层的构建,每一层构建完成就不会发生改变, ...

  7. SQL Server 数据库内部版本号

    数据库还原或版本升级出现版本错误时可参考 可以利用SQL语句查看本机数据库版本:select @@VERSION 如果你不确定是源数据库的版本,下面的映射表的SQL Server版本的内部版本号,以便 ...

  8. 遗传算法 | Java版GA_TSP(我的第一个Java程序)

    嗯哼,第一次写博客,准确说是第一次通过文字的方式记录自己的工作,闲话少叙,技术汪的博客就该直奔技术主题(关于排版问题,会在不断写博客的过程中慢慢学习,先将就着用吧,重在技术嘛~~~). 遗传算法(Ge ...

  9. 1-Linux运维人员要求

    linux 运维: 1.linux基础操作命令2.linux基础服务搭建3.文本处理命令4.shell脚本编程 python perl php5.数据库 mysql oracle6.lvs集群 热备 ...

  10. 关于android 5.0报错:dlopen failed: couldn't map ... Permission denied

    问题描述: 我的应用当中集成了一个安全相关的sdk,而这个sdk中使用的so是加过壳的. 它加载native so的方式是:Java System.loadLibrary --> native ...