[loj3180]天桥

当离开天桥\(A\)时,对其分类讨论:

  • 直接进入另一段天桥\(B\),此时位于\(A,B\)的公共端点

  • 向上经过另一段天桥\(B\),若该点不为\(B\)端点,则考虑调整

    具体的,不断撤回上一步,直至当前建筑高度\(\ge B\)或回到起点

    若为前者,显然此时在\(B\)范围内,不妨直接从该处进入\(B\)

    若为后者,则两者间建筑均\(<B\),其即为起点某侧第一个\(\ge B\)的建筑

  • 向下经过另一段天桥\(B\),若该点不为\(A\)端点,可以类似的从后往前调整

综上,仅需考虑以下几类关键点:

  • 起点、终点、天桥的端点
  • 对于某天桥,起点/终点左右两侧第一个$\ge $其的建筑处
  • 上述点下方第一个有天桥经过的点

点数和边数均为为\(O(m)\),时间复杂度为\(O(n+m\log m)\)

#include<bits/stdc++.h>
using namespace std;
#define L (k<<1)
#define R (L+1)
#define mid (l+r>>1)
typedef long long ll;
const int N=100005,M=10000000;
int n,m,V,st,ed,X[N],y[N],l[N],r[N],h[N],H[N];
vector<int>v[N],vq[N],vu[N];
vector<pair<int,int> >v0;
vector<pair<int,int> >::iterator it;
unordered_map<int,int>id[N];
namespace Seg1{
	int f[N<<2];
	void build(int k,int l,int r){
		if (l==r)f[k]=y[l];
		else{
			build(L,l,mid),build(R,mid+1,r);
			f[k]=max(f[L],f[R]);
		}
	}
	int findL(int k,int l,int r,int x,int y){
		if ((l>x)||(f[k]<y))return 0;
		if (l==r)return l;
		int ans=findL(R,mid+1,r,x,y);
		return (ans ? ans : findL(L,l,mid,x,y));
	}
	int findR(int k,int l,int r,int x,int y){
		if ((r<x)||(f[k]<y))return 0;
		if (l==r)return l;
		int ans=findR(L,l,mid,x,y);
		return (ans ? ans : findR(R,mid+1,r,x,y));
	}
};
namespace Seg2{
	int f[N<<2];
	void update(int k,int l,int r,int x,int y,int z){
		if ((l>y)||(x>r))return;
		if ((x<=l)&&(r<=y)){f[k]=z;return;}
		if (f[k])f[L]=f[R]=f[k],f[k]=0;
		update(L,l,mid,x,y,z),update(R,mid+1,r,x,y,z);
	}
	int query(int k,int l,int r,int x){
		if (f[k])return f[k];
		if (l==r)return 0;
		if (x<=mid)return query(L,l,mid,x);
		return query(R,mid+1,r,x);
	}
};
namespace Graph{
	int E,head[M],vis[M];ll d[M];
	struct List{int nex,to,len;}e[M];
	priority_queue<pair<ll,int> >q;
	void init(){
		memset(head,-1,sizeof(head));
	}
	void add(int x,int y,int z){
		e[E]=List{head[x],y,z},head[x]=E++;
		e[E]=List{head[y],x,z},head[y]=E++;
	}
	ll dijkstra(){
		memset(d,0x3f,sizeof(d));
		d[st]=0,q.push(make_pair(0,st));
		while (!q.empty()){
			int k=q.top().second;q.pop();
			if (vis[k])continue;
			vis[k]=1;
			for(int i=head[k];i!=-1;i=e[i].nex)
				if (d[e[i].to]>d[k]+e[i].len){
					d[e[i].to]=d[k]+e[i].len;
					q.push(make_pair(-d[e[i].to],e[i].to));
				}
		}
		return (d[ed]==d[0] ? -1 : d[ed]);
	}
};
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)scanf("%d%d",&X[i],&y[i]);
	for(int i=1;i<=m;i++){
		scanf("%d%d%d",&l[i],&r[i],&h[i]);
		l[i]++,r[i]++;
	}
	scanf("%d%d",&st,&ed);
	st++,ed++;
	if (st>ed)swap(st,ed);
	memcpy(H,h,sizeof(H));
	sort(H+1,H+m+1);
	for(int i=1;i<=m;i++)h[i]=lower_bound(H+1,H+m+1,h[i])-H;
	Seg1::build(1,1,n);
	for(int i=1;i<=m;i++){
		vq[h[i]].push_back(l[i]);
		vq[h[i]].push_back(r[i]);
		if ((l[i]<st)&&(st<r[i])){
			int x=Seg1::findL(1,1,n,st,H[h[i]]),y=Seg1::findR(1,1,n,st,H[h[i]]);
			if ((x)&&(x>l[i]))vq[h[i]].push_back(x);
			if ((y)&&(y<r[i]))vq[h[i]].push_back(y);
		}
		if ((l[i]<ed)&&(ed<r[i])){
			int x=Seg1::findL(1,1,n,ed,H[h[i]]),y=Seg1::findR(1,1,n,ed,H[h[i]]);
			if ((x)&&(x>l[i]))vq[h[i]].push_back(x);
			if ((y)&&(y<r[i]))vq[h[i]].push_back(y);
		}
	}
	id[st][0]=++V,id[ed][0]=++V;
	v[st].push_back(0),v[ed].push_back(0);
	for(int i=1;i<=m;i++){
		sort(vq[i].begin(),vq[i].end());
		vq[i].resize(unique(vq[i].begin(),vq[i].end())-vq[i].begin());
		for(int j:vq[i])id[j][i]=++V,v[j].push_back(i);
	}
	for(int i=1;i<=m;i++)vu[h[i]].push_back(i);
	for(int i=1;i<=m;i++){
		for(int j:vq[i]){
			int x=Seg2::query(1,1,n,j);
			if ((x)&&(!id[j][x])){
				id[j][x]=++V;
				v[j].push_back(x);
			}
		}
		for(int j:vu[i])Seg2::update(1,1,n,l[j],r[j],i);
	}
	for(int i=1;i<=n;i++)sort(v[i].begin(),v[i].end());
	for(int i=1;i<=m;i++)vq[i].clear();
	for(int i=1;i<=n;i++)
		for(int j:v[i])vq[j].push_back(i);
	Graph::init();
	for(int i=1;i<=n;i++){
		if (v[i].empty())continue;
		for(int j=1;j<v[i].size();j++){
			int x=v[i][j],y=v[i][j-1];
			Graph::add(id[i][x],id[i][y],H[x]-H[y]);
		}
	}
	for(int i=1;i<=m;i++){
		v0.clear();
		for(int j:vu[i])v0.push_back(make_pair(l[j],r[j]));
		sort(v0.begin(),v0.end());
		for(int j=1;j<vq[i].size();j++){
			int x=vq[i][j],y=vq[i][j-1];
			it=lower_bound(v0.begin(),v0.end(),make_pair(y+1,0));
			if ((it==v0.begin())||((*--it).second<x))continue;
			Graph::add(id[x][i],id[y][i],X[x]-X[y]);
		}
	}
	st=id[st][0],ed=id[ed][0];
	printf("%lld\n",Graph::dijkstra());
	return 0;
}
posted @ 2020-08-08 09:12  PYWBKTDA  阅读(157)  评论(0编辑  收藏  举报