3073: [Pa2011]Journeys

Time Limit: 20 Sec  Memory Limit: 512 MB

Description

 
 
Seter建造了一个很大的星球,他准备建造N个国家和无数双向道路。N个国家很快建造好了,用1..N编号,但是他发现道路实在太多了,他要一条条建简直是不可能的!于是他以如下方式建造道路:(a,b),(c,d)表示,对于任意两个国家x,y,如果a<=x<=b,c<=y<=d,那么在xy之间建造一条道路。Seter保证一条道路不会修建两次,也保证不会有一个国家与自己之间有道路。
Seter好不容易建好了所有道路,他现在在位于P号的首都。Seter想知道P号国家到任意一个国家最少需要经过几条道路。当然,Seter保证P号国家能到任意一个国家。
 
 
 
注意:可能有重边

Input

 
第一行三个数N,M,P。N<=500000,M<=100000。
后M行,每行4个数A,B,C,D。1<=A<=B<=N,1<=C<=D<=N。
 
 
 

Output

 
N行,第i行表示P号国家到第i个国家最少需要经过几条路。显然第P行应该是0。
 
 

Sample Input

5 3 4
1 2 4 5
5 5 4 4
1 1 3 3

Sample Output

1
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 -- 线段树优化最短路的更多相关文章

  1. bzoj 3073 [Pa2011]Journeys ——线段树优化连边

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3073 建两棵线段树,一棵孩子向父亲连边,是走出去的:一棵父亲向孩子连边,是走进来的. 注意第 ...

  2. 【bzoj3073】[Pa2011]Journeys 线段树优化建图+堆优化Dijkstra

    题目描述 Seter建造了一个很大的星球,他准备建造N个国家和无数双向道路.N个国家很快建造好了,用1..N编号,但是他发现道路实在太多了,他要一条条建简直是不可能的!于是他以如下方式建造道路:(a, ...

  3. BZOJ3073: [Pa2011]Journeys(线段树优化建图 Dijkstra)

    题意 \(n\)个点的无向图,构造\(m\)次边,求\(p\)到任意点的最短路. 每次给出\(a, b, c, d\) 对于任意\((x_{a \leqslant x \leqslant b}, y_ ...

  4. BZOJ_3073_[Pa2011]Journeys_线段树优化建图+BFS

    BZOJ_3073_[Pa2011]Journeys_线段树优化建图+BFS Description Seter建造了一个很大的星球,他准备建造N个国家和无数双向道路.N个国家很快建造好了,用1..N ...

  5. 【BZOJ3073】[Pa2011]Journeys 线段树+堆优化Dijkstra

    [BZOJ3073][Pa2011]Journeys Description Seter建造了一个很大的星球,他准备建造N个国家和无数双向道路.N个国家很快建造好了,用1..N编号,但是他发现道路实在 ...

  6. 【题解】Journeys(线段树优化连边)

    [#3073. Pa2011]Journeys (线段树优化连边) 这张图太直观了,直接讲透了线段树优化连边的原理和正确性. 考虑建立两颗线段树,一颗是外向树,一颗是内向树,相当于网络流建模一样,我们 ...

  7. DS线段树优化最短路&&01bfs浅谈

    1简介 为什么需要?原因很简单,当需要有大量的边去连时,用线段树优化可以直接用点连向区间,或从区间连向点,或从区间连向区间,如果普通连边,复杂度是不可比拟的.下面简单讲解一下线段树(ST)优化建图. ...

  8. bzoj 3073 Journeys —— 线段树优化连边

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3073 建两棵线段树,一棵从下往上连边,一棵从上往下连边,叶子节点之间也有连边: 区间向区间连 ...

  9. BZOJ 3073: [Pa2011]Journeys Dijkstra+线段树优化建图

    复习一下线段树优化建图:1.两颗线段树的叶子节点的编号是公用的. 2.每次连边是要建两个虚拟节点 $p1,p2$ 并在 $p1,p2$ 之间连边. #include <bits/stdc++.h ...

随机推荐

  1. webpack中的静态资源处理

    你可能已经注意到,在我们的项目结构里,有两个静态文件的路径,分别是:src/assets 和 static/.那这两个到底有什么区别呢? Webpacked 资源 为了回答这个问题,我们首先需要理解w ...

  2. DAY1-GO初识(概述)

    一.概述 1.特征 1.1.语法简单:规则严谨.保留指针.但默认阻止指针运算.将切片和字典作为内置类型.更好的维护性: 1.2.并发模型:运行时用GOroutine,一个关键字.简单而自然:搭配cha ...

  3. SPI最大传输速率【转】

    转自:https://www.silabs.com/community/mcu/8-bit/knowledge-base.entry.html/2017/01/13/spi_-asc0 问题 SPI作 ...

  4. postman中 form-data、x-www-form-urlencoded、raw、binary的区别 && 下载文件

    1.form-data:  就是http请求中的multipart/form-data,它会将表单的数据处理为一条消息,以标签为单元,用分隔符分开.既可以上传键值对,也可以上传文件.当上传的字段是文件 ...

  5. SP 页面缓存以及清除缓存

    JSP 页面缓存以及清除缓存 一.概述 缓存的思想可以应用在软件分层的各个层面.它是一种内部机制,对外界而言,是不可感知的. 数据库本身有缓存,持久层也可以缓存.(比如:hibernate,还分1级和 ...

  6. 使用 redis 减少 秒杀库存 超卖思路

    由于数据库查询的及插入的操作 耗费的实际时间要耗费比redis 要多, 导致 多人查询时库存有,但是实际插入数据库时却超卖 redis 会有效的减少相关的延时,对于并发量相对较少的 可以一用 publ ...

  7. Linux下软件的安装与管理

    1.源码安装方式 2.RPM包方式安装 3.yum安装方式 4.二进制软件安装方式 1.源码安装方式 (1)下载.解压Apache源码: mkdir /apache #在根目录下创建一个apache目 ...

  8. Porting of cURL to Android OS using NDK (from The Software Rogue)

    Porting of cURL to Android OS using NDK   In continuing my journey into Android territory, I decided ...

  9. CentOS/RHEL Linux安装EPEL第三方软件源

    https://www.vpser.net/manage/centos-rhel-linux-third-party-source-epel.html

  10. Characters_of_the_Three_Kingdoms - 三国人物结构化数据

    Characters_of_the_Three_Kingdoms - 三国人物结构化数据 三国人物结构化数据 为什么会有这个项目 需求1:摆脱网上那些长篇累牍的文章: 需求2:只是想简单查看下人物姓甚 ...