考虑将所有交点作为关键点来建图跑最短路,但图上的关键点数量最坏为$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. 洛谷1429 平面最近点对(KDTree)

    qwq(明明可以直接分治过掉的) 但是还是当作联系了 首先,对于这种点的题,很显然的套路,我们要维护一个子树\(mx[i],mn[i]\)分别表示每个维度的最大值和最小值 (这里有一个要注意的东西!就 ...

  2. Billu_b0x2内网渗透(多种提权方法)靶场-vulnhub

    个人博客阅读体验更佳 本次来试玩一下vulnhub上的Billu_b0x2,下载地址. 下载下来后是 .ova 格式,建议使用vitualbox进行搭建,vmware可能存在兼容性问题.靶场推荐使用N ...

  3. dubbo注册中心占位符无法解析问题(二)

    dubbo注册中心占位符无法解析问题 前面分析了dubbo注册中心占位符无法解析的问题. 并给出了2种解决办法: 降低mybatis-spring的版本至2.0.1及以下 自定义MapperScann ...

  4. 最详细的Android SDK下载安装及配置教程-------全文均为引用

    <https://www.cnblogs.com/gufengchen/p/11038029.html>

  5. elasticsearch嵌套对象的映射

    在es中,我们有时候可能需要映射,{ "field" : "xx" , "field01" : [] }这样格式的嵌套对象,默认情况下es会 ...

  6. HZOI帝国2019欢乐时刻

    前言: update 只是恢复一下原来手残删掉的博客,不是在水,嘤嘤嘤 update 以后改成Stack,但是之前的就懒得改了... by 10.31 为了窝的访问量大家的好心情,模仿学长搞了一个这个 ...

  7. Netty:Netty中的零拷贝(Zero Copy)

    零复制概念: " 零复制"描述了计算机操作,其中CPU不执行将数据从一个存储区复制到另一个存储区的任务.通过网络传输文件时,通常用于节省CPU周期和内存带宽. WIKI的定义中,我 ...

  8. 数据流中的中位数 牛客网 剑指Offer

    数据流中的中位数 牛客网 剑指Offer 题目描述 如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值.如果从数据流中读出偶数个数值,那么中位数就 ...

  9. Git 极速上手(超简单)

    前言:本文主要介绍了一种快速入门使用Git的方法,通过四步完成本地仓库构建和推送到远程仓库(Github.Gitee码云),简单说明最常用的命令,不需要明白Git的原理即可使用,本文不介绍具体原理. ...

  10. 二层组网AP上线

    一.实验目的 1)掌握配置WLAN源接口的命令 2)掌握配置DHCP服务器的命令 3)掌握手工确认AP上线的方法a 二.实验仪器设备及软件 仪器设备:一台AC,四台AP 软件:ENSP 三.实验原理 ...