【HDU】6110 路径交(2017百度之星) 线段树+RMQ-LCA+树链的交
【题意】给定n个点的带边权树,m条编号1~m的路径,Q次询问编号区间[L,R]所有链的交集的长度。n<=500000。
【算法】线段树+RMQ-LCA+树链的交
【题解】树链的交:记一条链为(a1,b1),LCA为c1。另一条链为(a2,b2),LCA为c2。记a1a2,a1b2,b1a2,b1b2的LCA为d1,d2,d3,d4,按深度排序后得deep[d1]<=deep[d2]<=deep[d3]<=deep[d4],deep[c1]<=deep[c2]。
两条链有交集当且仅当deep[c1]<=deep[d1]&&deep[c2]<=deep[d3],此时树链(d3,d4)是两条链的交。(判断是否有交还有另一种方法:一条链的LCA在另一条链上时有交)
基于此,用线段树维护m条链的交集,回答询问。用RMQ-LCA预处理后可以降低复杂度(注意欧拉序开2倍)。
总复杂度O(n log n)。
- #include<cstdio>
- #include<cstring>
- #include<cctype>
- #include<algorithm>
- #define ll long long
- using namespace std;
- int read(){
- char c;int s=,t=;
- while(!isdigit(c=getchar()))if(c=='-')t=-;
- do{s=s*+c-'';}while(isdigit(c=getchar()));
- return s*t;
- }
- const int maxn=;
- int dfn[maxn*],p[maxn],first[maxn],deep[maxn],Q[maxn*][],c[],d[],tot=,num=;
- ll dis[maxn];
- int logs[maxn*],n,m;
- struct edge{int v,w,from;}e[maxn*];
- struct cyc{int x,y;}O[maxn];
- struct tree{int l,r;cyc o;}t[maxn*];
- void insert(int u,int v,int w){tot++;e[tot].v=v;e[tot].w=w;e[tot].from=first[u];first[u]=tot;}
- void dfs(int x,int fa){
- dfn[++num]=x;
- if(!p[x])p[x]=num;
- for(int i=first[x];i;i=e[i].from)if(e[i].v!=fa){
- deep[e[i].v]=deep[x]+;
- dis[e[i].v]=dis[x]+e[i].w;
- dfs(e[i].v,x);
- dfn[++num]=x;
- }
- }
- void prepare(){
- logs[]=-;for(int i=;i<=num;i++)logs[i]=logs[i>>]+;
- for(int i=;i<=num;i++)Q[i][]=dfn[i];
- for(int j=;(<<j)<=num;j++){
- for(int i=;i+(<<j)-<=num;i++){
- if(deep[Q[i][j-]]<deep[Q[i+(<<(j-))][j-]])Q[i][j]=Q[i][j-];
- else Q[i][j]=Q[i+(<<(j-))][j-];
- }
- }
- }
- int lca(int x,int y){
- if(p[x]>p[y])swap(x,y);
- int k=logs[p[y]-p[x]+];
- return deep[Q[p[x]][k]]<deep[Q[p[y]-(<<k)+][k]]?Q[p[x]][k]:Q[p[y]-(<<k)+][k];
- }
- bool cmp(int a,int b){return deep[a]<deep[b];}
- cyc merge(cyc o1,cyc o2){
- if(!o1.x||!o2.x)return (cyc){,};
- d[]=lca(o1.x,o2.x);d[]=lca(o1.x,o2.y);d[]=lca(o1.y,o2.x);d[]=lca(o1.y,o2.y);
- c[]=lca(o1.x,o1.y);c[]=lca(o2.x,o2.y);
- sort(d+,d++,cmp);if(deep[c[]]>deep[c[]])swap(c[],c[]);
- if(deep[c[]]<=deep[d[]]&&deep[c[]]<=deep[d[]])return (cyc){d[],d[]};else return (cyc){,};//
- }
- void build(int k,int l,int r){
- t[k].l=l;t[k].r=r;
- if(l==r){t[k].o=O[l];return;}
- int mid=(l+r)>>;
- build(k<<,l,mid);build(k<<|,mid+,r);
- t[k].o=merge(t[k<<].o,t[k<<|].o);
- }
- cyc query(int k,int l,int r){
- if(l<=t[k].l&&t[k].r<=r)return t[k].o;
- int mid=(t[k].l+t[k].r)>>;cyc x=(cyc){-,};
- if(l<=mid)x=query(k<<,l,r);
- if(r>mid){if(~x.x)x=merge(x,query(k<<|,l,r));else x=query(k<<|,l,r);}
- return x;
- }
- int main(){
- n=read();
- for(int i=;i<n;i++){
- int u=read(),v=read(),w=read();
- insert(u,v,w);insert(v,u,w);
- }
- dfs(,);
- prepare();
- m=read();
- for(int i=;i<=m;i++)O[i].x=read(),O[i].y=read();
- build(,,m);
- int T=read();
- while(T--){
- int l=read(),r=read();cyc x;
- x=query(,l,r);
- if(!x.x)printf("0\n");else
- printf("%lld\n",dis[x.x]+dis[x.y]-*dis[lca(x.x,x.y)]);
- }
- return ;
- }
这题WA之后对拍不出错,发现是生成的数据每个点的父亲编号严格小于它,导致深度关系和编号等价。
然后我在判断c1<=d1&&c2<=d3的时候比较了编号而非深度,于是GG。
【HDU】6110 路径交(2017百度之星) 线段树+RMQ-LCA+树链的交的更多相关文章
- 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"百度之星 ...
- HDU 6109 数据分割 【并查集+set】 (2017"百度之星"程序设计大赛 - 初赛(A))
数据分割 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- HDU 6108 小C的倍数问题 【数学】 (2017"百度之星"程序设计大赛 - 初赛(A))
小C的倍数问题 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Sub ...
- HDU 6122 今夕何夕 【数学公式】 (2017"百度之星"程序设计大赛 - 初赛(A))
今夕何夕 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- HDU 6113 度度熊的01世界 【DFS】(2017"百度之星"程序设计大赛 - 初赛(A))
度度熊的01世界 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Su ...
- 2017"百度之星"程序设计大赛 - 复赛1005&&HDU 6148 Valley Numer【数位dp】
Valley Numer Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Tota ...
- 2017"百度之星"程序设计大赛 - 复赛1003&&HDU 6146 Pokémon GO【数学,递推,dp】
Pokémon GO Time Limit: 3000/1500 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- 2017"百度之星"程序设计大赛 - 复赛1001&&HDU 6144 Arithmetic of Bomb【java大模拟】
Arithmetic of Bomb Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Other ...
- HDU 6118 度度熊的交易计划 【最小费用最大流】 (2017"百度之星"程序设计大赛 - 初赛(B))
度度熊的交易计划 Time Limit: 12000/6000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total S ...
随机推荐
- WebSphere应用服务器内存泄漏探测与诊断工具选择最佳实践
内存泄漏是比较常见的一种应用程序性能问题,一旦发生,则系统的可用内存和性能持续下降:最终将导致内存不足(OutOfMemory),系统彻底宕掉,不能响应任何请求,其危害相当严重.同时,Java堆(He ...
- String、StringBuilder与StringBuffer的区别
1.String类是public.final修饰的. 在Java中,被final修饰的类是不允许被继承的,并且String它的成员方法都默认为final方法. 查看源码得知,String类其实是通过c ...
- IF与SWITCH
今晚刚刚看了一点儿<大话设计模式>这本书,看到它示例的第一个程序,好像有点理解IF与SWITCH的区别了.大致的思考了总结出来. IF适用于每个条件都必须判断,就是IF语句中的判断是不同类 ...
- CSS中可以和不可以继承的属性【转】
一.无继承性的属性 1.display:规定元素应该生成的框的类型 2.文本属性: vertical-align:垂直文本对齐 text-decoration:规定添加到文本的装饰 text-shad ...
- 【数据库_Postgresql】数据库主键自增长之加序列和不加序列2种方法
将表的主键进行序列增加之后可以在数据库层面自动主键id增长 方法如下:先建序列,然后建表关联id主键,然后添加语句,不用考虑id主键 DROP SEQUENCE IF EXISTS "pub ...
- C++解析-外传篇(1):异常处理深度解析
0.目录 1.异常的最终处理 2.结束函数terminate() 3.小结 1.异常的最终处理 问题: 如果在main函数中抛出异常会发生什么? 如果异常不处理,最后会传到哪里? 下面的代码的输出什么 ...
- Race to 1 UVA - 11762 (记忆dp概率)
#include <iostream> #include <cstdio> #include <sstream> #include <cstring> ...
- [洛谷P4626]一道水题 II
题目大意:求$lcm(1,2,3,\cdots,n)\pmod{100000007}$,$n\leqslant10^8$ 题解:先线性筛出质数,然后求每个质数最多出现的次数,可以用$\log_in$来 ...
- 连接Mysql数据库
JDBC连接数据库 创建一个以JDBC连接数据库的程序,包含7个步骤: 1.加载JDBC驱动程序: 在连接数据库之前,首先要加载想要连接的数据库的驱动到JVM(Java虚拟机), 这通过java.la ...
- 【BZOJ1758】【WC2010】重建计划(点分治,单调队列)
[BZOJ1758][WC2010]重建计划(点分治,单调队列) 题面 BZOJ 洛谷 Description Input 第一行包含一个正整数N,表示X国的城市个数. 第二行包含两个正整数L和U,表 ...