$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. iOS三句话实现文本转语音:AVSpeechSynthesizer

    一.介绍 从iOS5开始,iOS系统已经在siri上集成了语音合成的功能,但是是私有API.但是在iOS7,新增了一个简单的API----AVSpeechSynthesizer来做这件事情. 二.案例 ...

  2. 微信小程序 插件介绍

    小程序的插件是对一组js接口.自定义组件或页面的封装.插件不能独立运行,必须嵌入在其他小程序中才能被用户使用:而第三方小程序在使用插件时,也无法看到插件的代码.因此,插件适合用来封装自己的功能或服务, ...

  3. .net4.5注册到iis

    开始->所有程序->附件->鼠标右键点击“命令提示符”->以管理员身份运行->%windir%\Microsoft.NET\Framework\v4.0.30319\as ...

  4. SEO 第九章

    SEO第九章 本次课目标: 1.  外部优化之平台优化 2.  如何撰写SEO诊断方案 一.外部平台优化——百度系列平台 百度系列的平台都是属于百度自己的产品,排名都是比较高的,所以我们在做外部推广的 ...

  5. eject - 弹出可移动介质

    SYNOPSIS(总览) eject -h.breject [-vnrsfq] [<name>] eject [-vn] -d.breject [-vn] -a on|off|1|0 [& ...

  6. luogu 数列找不同-莫队

    https://www.luogu.org/problemnew/show/P3901 了解过莫队的人应该都清楚,莫队是一个优化的暴力,可以在相对暴力比较优的时间中,求出一段序列内的某些性质(例:数字 ...

  7. 【linux 06】 linux中的用户权限、文件权限与目录权限

    1.用户及用户组的概念: 1.文件所有者 2.用户组 3.用户 以root登录Linux之后,执行ls -al,会看到有关文件属性的信息 -rw-r--r--,第1个字符代表这个文件是“目录,文件或链 ...

  8. JavaScript基础对象---Map

    一.创建Map对象 Map 对象保存键值对.任何值(对象或者原始值) 都可以作为一个键或一个值 1.构造函数 语法:new Map([iterable])参数:         iterable  可 ...

  9. CSS3---关于背景

    1.background-origin:设置元素背景图片的原始起始位置. background-origin : border-box | padding-box | content-box;    ...

  10. PHP 配置文件php.ini文件优化

    PHP 5.3.3 safe_mode = On #控制php中的函数执行比如system() 这个函数可以调用系统目录 比如 rm ,打开这个配置之后,同时把很多文件操作的函数进行了权限控制 saf ...