$n \leq 500000$的树给$m \leq 500000$个路径,$q \leq 500000$个询问每次问一个区间的路径交。

路径交口诀:(前方高能)

判有交,此链有彼祖;

取其交,最深两两祖。

说成人话就是:判两条路径有没有交,只要一条链的lca在另一条链上就一定有交;取两条路径的交,把两条路径的端点两两求出四对lca,最深那两个就是路径交。

证明?我会还用口诀!

由于需要很多很多次查lca,这里用欧拉序+st表求。查区间路径交可以线段树也可以st表,毕竟重复的部分算两次没问题。

 //#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
//#include<time.h>
//#include<complex>
#include<algorithm>
#include<stdlib.h>
using namespace std; int n,m,q;
#define maxn 500011
struct Edge{int to,next,v;}edge[maxn<<]; int first[maxn],le=;
void in(int x,int y,int v) {Edge &e=edge[le]; e.to=y; e.v=v; e.next=first[x]; first[x]=le++;}
void insert(int x,int y,int v) {in(x,y,v); in(y,x,v);} int len,dep[maxn],id[maxn],st[maxn<<][],Log[maxn<<];
#define LL long long
LL dis[maxn];
void dfs(int x,int fa)
{
st[++len][]=x; id[x]=len; dep[x]=dep[fa]+;
for (int i=first[x];i;i=edge[i].next)
{
Edge &e=edge[i]; if (e.to==fa) continue;
dis[e.to]=dis[x]+e.v; dfs(e.to,x); st[++len][]=x;
}
} void makest()
{
Log[]=-; for (int i=;i<=len;i++) Log[i]=Log[i>>]+;
for (int j=;j<=;j++)
for (int i=,to=len-(<<j)+;i<=to;i++)
st[i][j]=dep[st[i][j-]]<dep[st[i+(<<(j-))][j-]]?st[i][j-]:st[i+(<<(j-))][j-];
} int lca(int x,int y)
{
if (id[x]>id[y]) {int t=x;x=y;y=t;} x=id[x]; y=id[y];
int l=Log[y-x+];
return dep[st[x][l]]<dep[st[y-(<<l)+][l]]?st[x][l]:st[y-(<<l)+][l];
} struct Line{int x,y;}line[maxn];
bool cmpdep(const int a,const int b) {return dep[a]<dep[b];}
Line combine(Line a,Line b)
{
if (a.x==- || b.x==-) return (Line){-,-};
int l1=lca(a.x,a.y),l2=lca(b.x,b.y);
int t1=lca(l1,b.x),t2=lca(l1,b.y),t3=lca(a.x,l2),t4=lca(a.y,l2);
bool flag=;
if ((t1==l1 && dep[t1]>=dep[l2]) || (t2==l1 && dep[t2]>=dep[l2])) flag=;
if ((t3==l2 && dep[t3]>=dep[l1]) || (t4==l2 && dep[t4]>=dep[l1])) flag=;
if (!flag) return (Line){-,-};
int d[]; d[]=lca(a.x,b.x); d[]=lca(a.x,b.y); d[]=lca(a.y,b.x); d[]=lca(a.y,b.y);
sort(d,d+,cmpdep); return (Line){d[],d[]};
} struct SMT
{
struct Node
{
int ls,rs;
Line com;
}a[maxn<<];
int size,n;
void clear(int m) {size=; n=m;}
void up(int x)
{
int &p=a[x].ls,&q=a[x].rs;
a[x].com=combine(a[p].com,a[q].com);
}
void build(int &x,int L,int R)
{
x=++size;
if (L==R) {a[x].com=line[L]; a[x].ls=a[x].rs=; return;}
int mid=(L+R)>>;
build(a[x].ls,L,mid); build(a[x].rs,mid+,R); up(x);
}
void build() {int x; build(x,,n);}
int ql,qr;
Line Query(int x,int L,int R)
{
if (ql<=L && R<=qr) return a[x].com;
int mid=(L+R)>>; Line ans; bool flag=;
if (ql<=mid) ans=Query(a[x].ls,L,mid),flag=;
if (qr>mid) {if (flag) ans=combine(Query(a[x].rs,mid+,R),ans); else ans=Query(a[x].rs,mid+,R);}
return ans;
}
Line query(int L,int R) {ql=L; qr=R; return Query(,,n);}
}t; int main()
{
scanf("%d",&n);
for (int i=,x,y,v;i<n;i++) scanf("%d%d%d",&x,&y,&v),insert(x,y,v);
len=; dfs(,); makest();
scanf("%d",&m);
for (int i=;i<=m;i++) scanf("%d%d",&line[i].x,&line[i].y);
t.clear(m); t.build();
scanf("%d",&q);
while (q--)
{
int x,y; scanf("%d%d",&x,&y);
Line ans=t.query(x,y);
printf("%lld\n",dis[ans.x]+dis[ans.y]-*dis[lca(ans.x,ans.y)]);
}
return ;
}

hdu6110:路径交的更多相关文章

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

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

  2. hdu 6010 路径交

    hdu 6010 路径交(lca + 线段树) 题意: 给出一棵大小为\(n\)的树和\(m\)条路径,求第\(L\)条路径到第\(R\)条路径的交的路径的长度 思路: 本题的关键就是求路径交 假设存 ...

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

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

  4. 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"百度之星 ...

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

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

  6. [51nod 1830] 路径交

    问题描述 给定一棵n个点的树,以及m条路径,每次询问第L条到第R条路径的交集部分的长度(如果一条边同时出现在2条路径上,那么它属于路径的交集). 输入格式 第一行一个数n(n<=500,000) ...

  7. BZOJ1906树上的蚂蚁&BZOJ3700发展城市——RMQ求LCA+树链的交

    题目描述 众所周知,Hzwer学长是一名高富帅,他打算投入巨资发展一些小城市. Hzwer打算在城市中开N个宾馆,由于Hzwer非常壕,所以宾馆必须建在空中,但是这样就必须建立宾馆之间的连接通道.机智 ...

  8. hdu6110(线段树+lca)

    题目 http://acm.hdu.edu.cn/showproblem.php?pid=6110 分析 注意到,若干条路径的交一定也是条路径 我们可以维护一个线段树,seg[l..r]存着第l条~第 ...

  9. UOJ #150 【NOIP2015】 运输计划

    题目描述 公元 \(2044\) 年,人类进入了宇宙纪元. \(L\) 国有 \(n\) 个星球,还有 \(n-1\) 条双向航道,每条航道建立在两个星球之间,这 \(n-1\) 条航道连通了 \(L ...

随机推荐

  1. [转]IntelliJ IDEA 自定义方法注解模板

    IntelliJ IDEA 自定义方法注解模板 置顶2017年08月02日 18:04:36 阅读数:32592 最近没啥事开始正式用Eclipse 转入 idea工具阵营,毕竟有70%的开发者在使用 ...

  2. poj1857 To Europe! To Europe!

    思路: 一维dp. 实现: #include <cstdio> #include <iostream> using namespace std; const int INF = ...

  3. JavaScript 的垃圾回收与内存泄露

    JavaScript采用垃圾自动回收机制,运行时环境会自动清理不再使用的内存,因此javascript无需像C++等语言一样手动释放无用内存. 在这之前先说一下垃圾回收的两种方式:引用计数与标记清除. ...

  4. HYSBZ 1503 郁闷的出纳员 (Splay树)

    题意: 作为一名出纳员,我的任务之一便是统计每位员工的工资.但是我们的老板反复无常,经常调整员工的工资.如果他心情好,就可能把每位员工的工资加上一个相同的量.反之,如果心情不好,就可能把他们的工资扣除 ...

  5. HDU 5416 CRB and Tree (技巧)

    题意:给一棵n个节点的树(无向边),有q个询问,每个询问有一个值s,问有多少点对(u,v)的xor和为s? 注意:(u,v)和(v,u)只算一次.而且u=v也是合法的. 思路:任意点对之间的路径肯定经 ...

  6. Mybatis(一)入门

    mybatis使用的三个部分数据查询主体 : SqlSession查询映射层 : Mapper接口数据维护层 : Bean 设计一.添加maven依赖<!-- mybatis依赖 -->& ...

  7. Zend Studio 修改“代码字体和大小”

  8. 对faster rcnn代码讲解的很好的一个

    http://www.cnblogs.com/houkai/p/6824455.html http://blog.csdn.net/u014696921/article/details/6032142 ...

  9. PHP07 函数

    学习要点 函数的定义 自定义函数 函数的工作原理和结构化编程 PHP变量范围 声明及应用各种形式的PHP函数 递归函数 使用自定义函数库 匿名函数和闭包 常用PHP系统函数 PHP7函数新特性 函数的 ...

  10. PHP03 移动互联网和PHP

    学习要点 移动互联网 云计算 网络通信协议 Apache http服务器 PHP运行原理 学习目标 理解网络通信协议 掌握PHP运行原理 WAMP开发环境的搭建   移动互联网 定义 移动互联网,就是 ...