https://www.zybuluo.com/ysner/note/1295471

题面

\(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\)号国家能到任意一个国家。

  • \(n\leq5*10^5,m\leq10^6\)

解析

显然不能照着题面说的去建边啊,空间复杂度\(O(n^2)\)惹不起。

一般来说,当边数过多的时候,一般都有一种使边数变少的方法:线段树优化连边

首先要有两颗线段树,一颗维护出发区间,一颗维护到达区间。(要不然会重复)

如果要在对应的两个区间建边,可以建单向边,从一个区间(线段树)向一个新建点连边,边权赋为\(1\);再把这点连向另一个区间(线段树),边权赋为\(0\)。

如果要建反向边,再新建一个点就可以了。

(理性思考一下发现与题目意思是等价的)

在出发线段树内部,由子结点向父结点建边;在到达线段树内部,由父结点向子结点建边。边权均为\(0\)。毕竟区间内部移动应该是(可看为)不需要经过道路的。

然后两颗线段树对应结点建边权为\(0\)的双向边。

所以这个建边的空间复杂度是多少呢?

线段树内部建边\(O(2nlogn)\),线段树对应点连边\(O(nlogn)\),区间建边\(O(m*?)\)。

所以建边数组要使劲往大开。

  1. #include<iostream>
  2. #include<cmath>
  3. #include<cstdio>
  4. #include<cstdlib>
  5. #include<cstring>
  6. #include<algorithm>
  7. #include<queue>
  8. #define ll long long
  9. #define re register
  10. #define il inline
  11. #define ls x<<1
  12. #define rs x<<1|1
  13. #define fp(i,a,b) for(re int i=a;i<=b;i++)
  14. #define fq(i,a,b) for(re int i=a;i>=b;i--)
  15. using namespace std;
  16. const int N=1e7+100;
  17. int n,m,p,st[N],ed[N],id[2][N],tot,h[N],cnt,dis[N];
  18. bool vis[N];
  19. struct Edge{int to,nxt,w;}e[N];
  20. il void add(re int u,re int v,re int w){e[++cnt]=(Edge){v,h[u],w};h[u]=cnt;}
  21. struct node{int u,dis;il bool operator < (const node &o) const {return dis>o.dis;}};
  22. priority_queue<node>Q;
  23. il ll gi()
  24. {
  25. re ll x=0,t=1;
  26. re char ch=getchar();
  27. while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
  28. if(ch=='-') t=-1,ch=getchar();
  29. while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
  30. return x*t;
  31. }
  32. il void Build(re int x,re int l,re int r)
  33. {
  34. id[0][x]=++tot;id[1][x]=++tot;
  35. if(l==r)
  36. {
  37. st[l]=id[0][x];ed[l]=id[1][x];
  38. add(id[0][x],id[1][x],0);
  39. add(id[1][x],id[0][x],0);
  40. return;
  41. }
  42. re int mid=l+r>>1;
  43. Build(ls,l,mid);Build(rs,mid+1,r);
  44. add(id[0][ls],id[0][x],0);add(id[0][rs],id[0][x],0);
  45. add(id[1][x],id[1][ls],0);add(id[1][x],id[1][rs],0);
  46. }
  47. il void Insert(re int x,re int l,re int r,re int ql,re int qr,re int u,re int op)
  48. {
  49. if(ql<=l&&r<=qr)
  50. {
  51. if(!op) add(id[0][x],u,1);
  52. else add(u,id[1][x],0);
  53. return;
  54. }
  55. re int mid=l+r>>1;
  56. if(ql<=mid) Insert(ls,l,mid,ql,qr,u,op);
  57. if(qr>mid) Insert(rs,mid+1,r,ql,qr,u,op);
  58. }
  59. il void Dijstra()
  60. {
  61. memset(dis,63,sizeof(dis));
  62. Q.push((node){st[p],0});dis[st[p]]=0;
  63. while(!Q.empty())
  64. {
  65. re int u=Q.top().u;Q.pop();
  66. vis[u]=1;
  67. for(re int i=h[u];i;i=e[i].nxt)
  68. {
  69. re int v=e[i].to;
  70. if(dis[v]>dis[u]+e[i].w)
  71. {
  72. dis[v]=dis[u]+e[i].w;
  73. Q.push((node){v,dis[v]});
  74. }
  75. }
  76. while(!Q.empty()&&vis[Q.top().u]) Q.pop();
  77. }
  78. }
  79. int main()
  80. {
  81. n=gi();m=gi();p=gi();
  82. Build(1,1,n);
  83. fp(i,1,m)
  84. {
  85. re int A=gi(),B=gi(),C=gi(),D=gi();
  86. ++tot;
  87. Insert(1,1,n,A,B,tot,0);
  88. Insert(1,1,n,C,D,tot,1);
  89. ++tot;
  90. Insert(1,1,n,C,D,tot,0);
  91. Insert(1,1,n,A,B,tot,1);
  92. }
  93. Dijstra();
  94. fp(i,1,n) printf("%d\n",dis[ed[i]]);
  95. return 0;
  96. }

然而时间不够优秀。。。

注意到边权只有\(0/1\),我们实际上可以优化最短路算法中的那个\(log\)。

每次更新完,我们可以把为\(0\)的放在队首,为\(1\)的放在队尾。因为从\(0\)转移过来的肯定比从\(1\)的更优。

  1. il void Dijstra()
  2. {
  3. memset(dis,63,sizeof(dis));
  4. Q.push_back(st[p]);dis[st[p]]=0;
  5. while(!Q.empty())
  6. {
  7. re int u=Q.front();Q.pop_front();
  8. if(vis[u]) continue;vis[u]=1;
  9. for(re int i=h[u];i;i=e[i].nxt)
  10. {
  11. re int v=e[i].to;
  12. if(dis[v]>dis[u]+e[i].w)
  13. {
  14. dis[v]=dis[u]+e[i].w;
  15. e[i].w?Q.push_back(v):Q.push_front(v);
  16. }
  17. }
  18. }
  19. }

[bzoj3073]Journeys的更多相关文章

  1. BZOJ3073 Journeys - 线段树优化建边

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

  2. [bzoj3073] Journeys 题解(线段树优化建图)

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

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

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

  4. bzoj3073: [Pa2011]Journeys 线段树优化建图

    bzoj3073: [Pa2011]Journeys 链接 BZOJ 思路 区间和区间连边.如何线段树优化建图. 和单点连区间类似的,我们新建一个点,区间->新点->区间. 又转化成了单点 ...

  5. BZOJ3073 : [Pa2011]Journeys

    用线段树套链表维护所有边,用set维护未访问过的点 然后BFS,每次在线段树上找边,然后在set中查询点 一条边使用之后就没有用了,所以在链表中将它删去 时间复杂度$O((n+m)\log n+m\l ...

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

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

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

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

  8. BZOJ3073 [Pa2011]Journeys[最短路—线段树优化建边]

    新技能get✔. 线段树优化建边主要是针对一类连续区间和连续区间之间建边的题,建边非常的优秀.. 这题中,每次要求$[l1,r1]$每一点向$[l2,r2]$每一点建无向边,然后单元最短路. 暴力建边 ...

  9. bzoj 3073: [Pa2011]Journeys -- 线段树优化最短路

    3073: [Pa2011]Journeys Time Limit: 20 Sec  Memory Limit: 512 MB Description     Seter建造了一个很大的星球,他准备建 ...

随机推荐

  1. python3.x Day4 模块!!

    json and pickle模块 用途是为了持久化信息,这种持久化方式可以和其他程序语言兼容,一般都支持json,json只能持久化数据,pickle是python特有的方式,可以持久化所有信息和数 ...

  2. Python之机器学习-波斯顿房价预测

    目录 波士顿房价预测 导入模块 获取数据 打印数据 特征选择 散点图矩阵 关联矩阵 训练模型 可视化 波士顿房价预测 导入模块 import pandas as pd import numpy as ...

  3. (十三)python 3 集合

    定义: 1.不同元素组成 2.无序 3.集合中的元素必须是不可变类型 创建集合 s = {1,2,3,4,5,6,7,8} 1.定义可变集合 >>> set_test = set(' ...

  4. BNUOJ 1585 Girls and Boys

    Girls and Boys Time Limit: 5000ms Memory Limit: 10000KB This problem will be judged on PKU. Original ...

  5. 【NOIP2017练习】鏖战字符串(斜率优化DP)

    题意: 在决胜局中,Abwad决定和nbc鏖战字符串,比的是谁能更快地将一个“量子态的字符串”删除.“量子态的字符串”的每个字符都有一个删除难度dif[i].“量子态的字符串”非常顽固,只能先分割成若 ...

  6. Layui导航、面包屑

    物不在多,有用则精! 学习使用链接 导航:导航一般指页面引导性频道集合,多以菜单的形式呈现,可应用于头部和侧边,是整个网页画龙点晴般的存在.面包屑结构简单,支持自定义分隔符.千万不要忘了加载 elem ...

  7. 学习日常笔记<day09>Http协议

    1 Http协议入门 1.1 什么是http协议 http协议: 对浏览器客户端 和  服务器端 之间数据传输的格式规范 1.2 查看http协议的工具 1)使用火狐的firebug插件(右键-> ...

  8. Swift 与 Kotlin 的简单对比

    一位国外的程序员认为 Swift 的语法与 Kotlin 相似,并整理了一些 Swift 和 Kotlin 的对比,下面是一些例子,大家不妨也看看. BASICS Hello World Swift ...

  9. 基于TensorFlow的图片识别服务

    1.使用TensorFlow Retrain进行图片分类训练 https://www.tensorflow.org/versions/master/how_tos/image_retraining/i ...

  10. Android.mk文件解析

     一.一个简单的Android.mk文件例如以下: LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := nativ ...