bzoj 3073: [Pa2011]Journeys -- 线段树优化最短路
3073: [Pa2011]Journeys
Time Limit: 20 Sec Memory Limit: 512 MB
Description
Input
Output
Sample Input
1 2 4 5
5 5 4 4
1 1 3 3
Sample Output
1
2
0
1
HINT
我们发现本题点数非常多,需要建的边也非常多,如果直接建图的话一定会TLE+MLE
但是我们会发现本题有一个很好的性质,就是连续一段区间都可以到达另外连续一段区间
如何优化这样连续的区间,我们就会想到一种数据结构——线段树
我们可以将线段树一段区间映射到这里,这样就可以用线段树上的几段完整表示整个区间,这也可以看成将点打包的思想
接下来我们考虑如何从【a,b】到【c,d】连边
首先,如果我们还是直接将每段线段连边的话它的复杂度还是很高
所以我们考虑抽象成新建两个点P1,P2,表示两段区间,这样从【a,b】到【c,d】,就是相当于从P1到P2连一条边
然后我们只要所有线段【a,b】向P1连边,P2向所有线段【c,d】连边就可以做到了
但是,这里还存在一个问题,就是如果把图建到一棵线段树中就会出现线段重叠,就会出问题
所以我们需要建两棵线段树A,B,表示从A会经过一条P边到B,这样就可以表示经过了一条边
然后我们对于A线段树中的点从儿子向父亲连一条权值为0的边(因为它本身属于这个集合,不需要代价)
从B线段树中的爹向儿子连一条权值为0的边(因为能到爹一定也能到儿子,不需要代价)
再从B中的叶子节点向A中对应叶子节点连一条权值为0的边(走完一条路径,到达对应点,继续从它开始出发)
这样,我们就可以跑最短路了
#include<map>
#include<cmath>
#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define inf 1000000007
#define ll long long
#define M 4000010
#define N 500010
inline int rd()
{
int x=,f=;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
}
int n,m,p;
int lj[M],to[M<<],v[M<<],fro[M<<],cnt,ls[N<<],rs[N<<],ra,rb,tot,val[N],dis[M];
inline int add(int a,int b,int c){fro[++cnt]=lj[a];to[cnt]=b;v[cnt]=c;lj[a]=cnt;}
void build(int l,int r,int &x,int op)
{
x=++tot;
if(l==r){if(op) val[l]=x;return;}
int mid=l+r>>;
build(l,mid,ls[x],op);build(mid+,r,rs[x],op);
if(op) add(ls[x],x,),add(rs[x],x,);
else add(x,ls[x],),add(x,rs[x],);
}
void fadd(int l,int r,int x,int y)
{
if(l==r){add(y,x,);return;}
int mid=l+r>>;
fadd(l,mid,ls[x],ls[y]);fadd(mid+,r,rs[x],rs[y]);
}
void padd(int l,int r,int p,int L,int R,int x,int op)
{
if(L==l&&R==r)
{
if(op) add(x,p,);
else add(p,x,);
return;
}
int mid=l+r>>;
if(L>mid) padd(mid+,r,p,L,R,rs[x],op);
else if(R<=mid) padd(l,mid,p,L,R,ls[x],op);
else
{
padd(l,mid,p,L,mid,ls[x],op);
padd(mid+,r,p,mid+,R,rs[x],op);
}
}
void link(int a,int b,int c,int d)
{
padd(,n,++tot,a,b,ra,);add(tot,tot+,);
padd(,n,++tot,c,d,rb,);
}
#define pa pair<int,int>
priority_queue<pa,vector<pa >,greater<pa > >q;
bool vs[M];
void dij()
{
memset(dis,0x3f,sizeof(dis));
int l=,r=,x;
dis[val[p]]=;
q.push(make_pair(,val[p]));
while(!q.empty())
{
x=q.top().second;q.pop();
if(vs[x]) continue;vs[x]=;
for(int i=lj[x];i;i=fro[i])
if(dis[to[i]]>dis[x]+v[i])
{
dis[to[i]]=dis[x]+v[i];
q.push(make_pair(dis[to[i]],to[i]));
}
}
}
int main()
{
int a,b,c,d;
n=rd();m=rd();p=rd();
build(,n,ra,);build(,n,rb,);fadd(,n,ra,rb);
for(int i=;i<=m;i++)
{
a=rd();b=rd();c=rd();d=rd();
link(a,b,c,d);link(c,d,a,b);
}
dij();
for(int i=;i<=n;i++) printf("%d\n",dis[val[i]]);
return ;
}
bzoj 3073: [Pa2011]Journeys -- 线段树优化最短路的更多相关文章
- bzoj 3073 [Pa2011]Journeys ——线段树优化连边
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3073 建两棵线段树,一棵孩子向父亲连边,是走出去的:一棵父亲向孩子连边,是走进来的. 注意第 ...
- 【bzoj3073】[Pa2011]Journeys 线段树优化建图+堆优化Dijkstra
题目描述 Seter建造了一个很大的星球,他准备建造N个国家和无数双向道路.N个国家很快建造好了,用1..N编号,但是他发现道路实在太多了,他要一条条建简直是不可能的!于是他以如下方式建造道路:(a, ...
- BZOJ3073: [Pa2011]Journeys(线段树优化建图 Dijkstra)
题意 \(n\)个点的无向图,构造\(m\)次边,求\(p\)到任意点的最短路. 每次给出\(a, b, c, d\) 对于任意\((x_{a \leqslant x \leqslant b}, y_ ...
- BZOJ_3073_[Pa2011]Journeys_线段树优化建图+BFS
BZOJ_3073_[Pa2011]Journeys_线段树优化建图+BFS Description Seter建造了一个很大的星球,他准备建造N个国家和无数双向道路.N个国家很快建造好了,用1..N ...
- 【BZOJ3073】[Pa2011]Journeys 线段树+堆优化Dijkstra
[BZOJ3073][Pa2011]Journeys Description Seter建造了一个很大的星球,他准备建造N个国家和无数双向道路.N个国家很快建造好了,用1..N编号,但是他发现道路实在 ...
- 【题解】Journeys(线段树优化连边)
[#3073. Pa2011]Journeys (线段树优化连边) 这张图太直观了,直接讲透了线段树优化连边的原理和正确性. 考虑建立两颗线段树,一颗是外向树,一颗是内向树,相当于网络流建模一样,我们 ...
- DS线段树优化最短路&&01bfs浅谈
1简介 为什么需要?原因很简单,当需要有大量的边去连时,用线段树优化可以直接用点连向区间,或从区间连向点,或从区间连向区间,如果普通连边,复杂度是不可比拟的.下面简单讲解一下线段树(ST)优化建图. ...
- bzoj 3073 Journeys —— 线段树优化连边
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3073 建两棵线段树,一棵从下往上连边,一棵从上往下连边,叶子节点之间也有连边: 区间向区间连 ...
- BZOJ 3073: [Pa2011]Journeys Dijkstra+线段树优化建图
复习一下线段树优化建图:1.两颗线段树的叶子节点的编号是公用的. 2.每次连边是要建两个虚拟节点 $p1,p2$ 并在 $p1,p2$ 之间连边. #include <bits/stdc++.h ...
随机推荐
- 利用__attribute__((section()))构建初始化函数表【转】
转自: https://mp.weixin.qq.com/s?__biz=MzAwMDUwNDgxOA==&mid=2652663356&idx=1&sn=7797629530 ...
- shell编程===执行shell脚本的四种方法
使用vim创建一个shell文件,命名 hello.sh #!/bin/bash echo "hello shell !" 在linux中进行加载 chmod +x ./hello ...
- Linux内存高,触发oom-killer问题解决
最近遇到两起Linux的内存问题,其一是触发了oom-killer导致系统挂 1. 首先确认该系统的版本是32位 ? #uname -a Linux alarm 2.6.9-67.ELsmp #1 S ...
- 62.Unique Paths---dp
题目链接 题目大意:给一个m*n的方格,从左上角走到右下角,中间无任何障碍,问有多少种走法. 法一:DFS,超时,简单模板深搜,无任何剪枝,结果一半的数据超时.代码如下: public int uni ...
- vue头像上传
项目四知识点 默认头像 选择头像 <template> <div class="adatar"> <img :src="adatar?ada ...
- FAQ1: 列表索引和切片问题
问题1. 超过列表成员个数的索引访问列表会出现IndexError错误,但是如果用切片去访问就不会报错,而是返回一个空列表.同样元组也是. >>> a=[1,2,3,4] >& ...
- RF和adaboost
通过对所有的决策树进行加总来预测新的数据(在分类时采用多数投票,在回归时采用平均).
- 安全控制 iptables
转自:http://www.opsers.org/linux-home/videos/chapter-netfilter-iptables-raiders.html 内容简介防火墙的概述iptable ...
- 深度学习方法(八):自然语言处理中的Encoder-Decoder模型,基本Sequence to Sequence模型
欢迎转载,转载请注明:本文出自Bin的专栏blog.csdn.net/xbinworld.技术交流QQ群:433250724,欢迎对算法.技术感兴趣的同学加入. Encoder-Decoder(编码- ...
- IF....Else循环
在Python中最简单的循环,if......else...... if语句是判断条件是否满足条件的,如果满足条件则执行if后面的语句:否则执行else的语句. #用户输入性别,进行判断sex = i ...