考虑将所有交点作为关键点来建图跑最短路,但图上的关键点数量最坏为$o(nm)$,需要优化
当$s=0$且$g=n-1$的部分分,有以下结论:
1.对于一段天桥$([l,r],y)$,不会从$(r,y)$向左移动到$(l,y)$,否则必然曾经过$(l,y')$,不如$(l,y')=>(l,y)$更优
2.对于一座天桥$([l,r],y)$,不会从竖直方向经过$(l',y)$,否则必然曾经过$(l,y')$,不如$(l,y')=>(l,y)=>(l',y)$更优
3.对于一座天桥$([l,r],y)$,不会从$(x,y)$向下移动,否则必然会再经过$(x',y)$或$(r,y')$,前者根据结论2一定不优,后者不如$(x,y)=>(r,y)=>(r,y')$更优
对于一座天桥$([l,r],y)$,其中$(x,y)$为关键点当且仅当$x=l$或$x=r$或其向上走经过的第一个交点为天桥端点,那么点数最多为$3m$,即解决了$s=0$且$t=n-1$的部分分
那么对于原题,先不妨假设$s<g$,那么对于一座天桥$([l,r],y)$,其要特殊考虑当且仅当$l<s$或$g<r$,以$l<s$为例:找到$s$左边/右边(包括$s$)第一个能上桥的点$a$和$b$($h_{a,b}\ge y$),那么将整座桥拆成$([l,a],y)$,$([a,b],y)$和$([b,r],y)$即可

  1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 100005
4 #define oo 1e15
5 #define L (k<<1)
6 #define R (L+1)
7 #define mid (l+r>>1)
8 #define pii pair<int,int>
9 #define mp make_pair
10 #define fi first
11 #define se second
12 struct ji{
13 int nex,to,len;
14 }edge[N*80];
15 struct build{
16 int x,h;
17 }bu[N];
18 struct bridge{
19 int l,r,y;
20 bool operator < (const bridge &k)const{
21 return (y<k.y)||(y==k.y)&&(l<k.l);
22 }
23 }br[N*5];
24 priority_queue<pair<long long,int> >q;
25 map<pii,int>mat;
26 vector<pii>v;
27 int V,E,n,m,s,t,f[N<<2],head[N*20],vis[N*20];
28 long long ans,d[N*20];
29 bool cmp(pii x,pii y){
30 return (x.se<y.se)||(x.se==y.se)&&(x.fi<y.fi);
31 }
32 void build(int k,int l,int r){
33 if (l==r){
34 f[k]=bu[l].h;
35 return;
36 }
37 build(L,l,mid);
38 build(R,mid+1,r);
39 f[k]=max(f[L],f[R]);
40 }
41 int find1(int k,int l,int r,int x,int y,int z){
42 if ((l>y)||(x>r)||(f[k]<z))return 0;
43 if (l==r)return l;
44 int a=find1(R,mid+1,r,x,y,z);
45 if (a)return a;
46 return find1(L,l,mid,x,y,z);
47 }
48 int find2(int k,int l,int r,int x,int y,int z){
49 if ((l>y)||(x>r)||(f[k]<z))return 0;
50 if (l==r)return l;
51 int a=find2(L,l,mid,x,y,z);
52 if (a)return a;
53 return find2(R,mid+1,r,x,y,z);
54 }
55 void update(int k,int l,int r,int x,int y,int z){
56 if ((l>y)||(x>r))return;
57 if ((x<=l)&&(r<=y)){
58 f[k]=max(f[k],z);
59 return;
60 }
61 update(L,l,mid,x,y,z);
62 update(R,mid+1,r,x,y,z);
63 }
64 int query(int k,int l,int r,int x){
65 if (l==r)return f[k];
66 if (x<=mid)return max(f[k],query(L,l,mid,x));
67 return max(f[k],query(R,mid+1,r,x));
68 }
69 void add(int x,int y,int z){
70 edge[E].nex=head[x];
71 edge[E].to=y;
72 edge[E].len=z;
73 head[x]=E++;
74 }
75 void split(int k,int x){
76 if ((x)&&(br[k].l<x)&&(x<br[k].r)){
77 br[++m]=bridge{br[k].l,x,br[k].y};
78 br[k].l=x;
79 }
80 }
81 void split(){
82 build(1,1,n);
83 for(int i=1;i<=m;i++){
84 int a,b;
85 if (br[i].l<s){
86 split(i,find1(1,1,n,1,s,br[i].y));
87 split(i,find2(1,1,n,s,n,br[i].y));
88 }
89 if (t<br[i].r){
90 split(i,find1(1,1,n,1,t,br[i].y));
91 split(i,find2(1,1,n,t,n,br[i].y));
92 }
93 }
94 }
95 void build(){
96 memset(head,-1,sizeof(head));
97 sort(v.begin(),v.end());
98 for(int i=0;i<v.size();i++)
99 if ((!i)||(v[i-1]!=v[i]))mat[v[i]]=++V;
100 for(int i=0,j=0;i<v.size();i=++j)
101 for(;((j<v.size())&&(v[j].fi==v[j+1].fi));j++)
102 if (v[j].se!=v[j+1].se){
103 add(mat[v[j]],mat[v[j+1]],v[j+1].se-v[j].se);
104 add(mat[v[j+1]],mat[v[j]],v[j+1].se-v[j].se);
105 }
106 sort(v.begin(),v.end(),cmp);
107 for(int i=1,j=0;i<=m;i++){
108 while ((br[i].y!=v[j].se)||(br[i].l!=v[j].fi))j++;
109 for(;((br[i].y!=v[j].se)||(br[i].r!=v[j].fi));j++)
110 if (v[j].fi!=v[j+1].fi){
111 add(mat[v[j]],mat[v[j+1]],bu[v[j+1].fi].x-bu[v[j].fi].x);
112 add(mat[v[j+1]],mat[v[j]],bu[v[j+1].fi].x-bu[v[j].fi].x);
113 }
114 }
115 }
116 long long dij(int s,int t){
117 memset(vis,0,sizeof(vis));
118 for(int i=1;i<=V;i++)d[i]=oo;
119 d[s]=0;
120 q.push(mp(0,s));
121 while (!q.empty()){
122 int k=q.top().se;
123 q.pop();
124 if (vis[k])continue;
125 vis[k]=1;
126 for(int i=head[k];i!=-1;i=edge[i].nex)
127 if (d[edge[i].to]>d[k]+edge[i].len){
128 d[edge[i].to]=d[k]+edge[i].len;
129 q.push(mp(-d[edge[i].to],edge[i].to));
130 }
131 }
132 return d[t];
133 }
134 int main(){
135 scanf("%d%d",&n,&m);
136 for(int i=1;i<=n;i++)scanf("%d%d",&bu[i].x,&bu[i].h);
137 for(int i=1;i<=m;i++){
138 scanf("%d%d%d",&br[i].l,&br[i].r,&br[i].y);
139 br[i].l++,br[i].r++;
140 }
141 scanf("%d%d",&s,&t);
142 s++,t++;
143 if (s>t)swap(s,t);
144 v.push_back(mp(s,0));
145 v.push_back(mp(t,0));
146 split();
147 sort(br+1,br+m+1);
148 memset(f,0,sizeof(f));
149 for(int i=1,j=1;i<=m;i++){
150 if (br[j].y<br[i].y)
151 for(;j<i;j++)update(1,1,n,br[j].l,br[j].r,br[j].y);
152 v.push_back(mp(br[i].l,br[i].y));
153 v.push_back(mp(br[i].r,br[i].y));
154 v.push_back(mp(br[i].l,query(1,1,n,br[i].l)));
155 v.push_back(mp(br[i].r,query(1,1,n,br[i].r)));
156 }
157 build();
158 ans=dij(mat[mp(s,0)],mat[mp(t,0)]);
159 if (ans==oo)ans=-1;
160 printf("%lld",ans);
161 }

[loj3180]天桥的更多相关文章

  1. .NET平台和C#编程的总结

    第一章   简单认识.NET框架    (1)首先我们得知道 .NET框架具有两个主要组件:公共语言进行时CLR(Common Language Runtime)和框架类库FCL(Framework ...

  2. 深入.NET平台和C#编程总结大全

    对于初学者的你,等到你把这个看完之后就更清楚地认知.NET和C#编程了,好了废话不多说,开始吧!                                                     ...

  3. 站在风口,你或许就是那年薪20w+的程序猿

    最近面试了一些人,也在群上跟一些群友聊起,发现现在的互联网真是热,一些工作才两三年的期望的薪资都是十几K的起,这真是让我们这些早几年就成为程序猿的情何以堪!正所谓是站在风口上,猪也能飞起来!我在这里就 ...

  4. VR/AR 非技术总结

    VR/AR 非技术总结 **欢迎转载~转载请注明Erma的博客 http://www.cnblogs.com/Erma-king/** 都说2016是VR/AR的元年,上半年我随着新技术的潮流进入了V ...

  5. PHP 二维数组根据某个字段排序

    二维数组根据某个字段排序有两种办法,一种是通过sort自己写代码,一种是直接用array_multisort排序函数 一. 手写arraysort PHP的一维数组排序函数: sort  对数组的值按 ...

  6. 一鼓作气 博客--第二篇 note2

    1.循环正常结束是指没有中间截断,即没有执行break; for i in range(10) print(i) else: print("循环正常结束") 2.嵌套循环 for ...

  7. Python之路第一课Day2--随堂笔记

    入门知识拾遗 一.bytes类型 bytes转二进制然后转回来 msg="张杨" print(msg) print(msg.encode("utf-8")) p ...

  8. 【与软件无关】2013赤峰地区C1科目三考试攻略【绝对原创】

    期待很久的科目三,终于在开考了.传说中的全部电子评判,让习惯给考官送礼的赤峰人民无所是从.据说前几天曾经有一个驾校,考了一整天,八十多个人一个没过的. 我这个攻略是今天通过考试后的一点心得,希望能有用 ...

  9. 这些年正Android - 身在他乡

    “从不敢想到想去做到,做到我想的,事实证明我并不像他们想象的那样脆弱.我只是需要一盏灯,一架钢琴,一支麦克风.曾经想象过做一名医生救死扶伤,也曾想过做律师,做记者,做奥运冠军,但是都没有结果.因为我最 ...

随机推荐

  1. SONiC架构分析

    目录 系统架构 设计原则 核心组件 SWSS 容器 syncd 容器 网络应用容器 内部通信模型 SubscriberStateTable NotificationProducer/Consumer ...

  2. redis编译安装、哨兵、集群

    编译安装 #下载源代码解压 wget https://download.redis.io/releases/redis-5.0.13.tar.gz -P /home/ tar -xvf /home/r ...

  3. 双系统升win11(grub启动问题修复与讲解)?!?

    起 最近win11不是出来了吗.(着急修复的可以直接跳到最后一步) 于是我就突发奇想给我半年没进去的windows升个级........ 于是我找到了我win11的升级包(从我一个同学哪儿) 工具都集 ...

  4. javascriptRemke之类的继承

    前言:es6之前在js中要实现继承,就必须要我们程序员在原型链上手动继承多对象的操作,但是结果往往存在漏洞,为解决这些问题,社区中出现了盗用构造函数.组合继承.原型式继承.寄生式继承等一系列继承方式, ...

  5. 在python中实现BASE64编码

    什么是Base64编码 BASE64是用于传输8Bit字节的编码方式之一,是一种基于64个可打印字符来表示二进制数据的方法. 如下是转换表:The Base64 Alphabet Base64编码可以 ...

  6. netty系列之:使用netty实现支持http2的服务器

    目录 简介 基本流程 CleartextHttp2ServerUpgradeHandler Http2ConnectionHandler 总结 简介 上一篇文章中,我们提到了如何在netty中配置TL ...

  7. 【Java虚拟机7】ClassLoader源码文档翻译

    前言 学习JVM类加载器,ClassLoader这个类加载器的核心类是必须要重视的. Notes:下方蓝色文字是自己的翻译(如果有问题请指正).黑色文字是源文档.红色文字是自己的备注. ClassLo ...

  8. 这样学BAT必面之软件设计原则,还不会就是我的问题

    学习设计原则是学习设计模式的基础.在实际开发过程中,并不要求所有代码都遵循设计原则,我们要考虑人力.时间.成本.质量,不能刻意追求完美,但要在适当的场景遵循设计原则,这体现的是一种平衡取舍,可以帮助我 ...

  9. 力扣 - 剑指 Offer 57. 和为s的两个数字

    题目 剑指 Offer 57. 和为s的两个数字 思路1(哈希表) 这题首先想到的是使用两个for遍历,查找是哪两个相加等于target,但是时间复杂度确实\(O(N^2)\),时间复杂度太高,因此我 ...

  10. 五分钟搞懂spring-cloud-square

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 初识spring-cloud-square 2021年 ...