題目
Description
Input
Output
輸出到文件 travel.out 中。
一行一個整數,表示從起點到終點的最小路程。
Sample Input
樣例 1 輸入:
3 2 14 5 1
4 6 6 10
0 7 3 9
1 2 8 5
Sample Output
樣例 1 輸出:
20
Data Constraint
Hint
樣例解釋
路線爲 (2,14) − (0,14) − (0,1) − (5,1)。
思路
考試的時候一時腦抽忘了可以離散化,結果30暴力沒打完GG
首先我們yy一下可以得到,最優路徑有一個軸是單調的,就說不可能兩個軸都走遠路
那麼怎麼判斷呢?
考慮一個方案:假設sx<tx,sy<ty,我們要證明x軸單調
考慮不斷往y+1方向走,被攔着了就往x+1走。如果在到y=ty之前x>tx就證明x軸要往回走,所以就不單調。
那麼現在我們知道了單調,考慮怎麼求答案
還是假設sx<tx,sy<ty
我們從左往右走,遇到障礙就向上下走,然後順着建築拐彎
這樣我們最多會分出2*n條路線
直接爆搜是O(2N)
考慮每一列都用一個set維護,那麼時間複雜度就變成了O(nlogn)
代碼
#include<bits/stdc++.h>
using namespace std;
const int N=4e5+77;
int n,sx,sy,tx,ty,ans;
struct M
{
int x1,y1,x2,y2;
} a[N];
int cmp(M a,M b)
{
return a.x1<b.x1;
}
struct ND
{
int x,d;
ND(int _x=0,int _d=0){x=_x,d=_d;}
};
int operator<(ND a,ND b) {return a.x<b.x;}
set<int> s;
int cnt;
set<int>::iterator it;
set<ND> t;
set<ND>::iterator it0,it1;
struct line{int x,y,t;} p[N];
int cmpl(line a,line b){return a.x<b.x;}
void solve()
{
cnt=0;
cnt++,p[cnt].x=sx,p[cnt].y=sy,p[cnt].t=-1;
cnt++,p[cnt].x=tx,p[cnt].y=ty,p[cnt].t=-2;
for(int i=1; i<=n; i++)
{
cnt++,p[cnt].x=a[i].x1,p[cnt].y=a[i].y1,p[cnt].t=1;
cnt++,p[cnt].x=a[i].x2,p[cnt].y=a[i].y1,p[cnt].t=2;
}
sort(p+1,p+1+cnt,cmpl);
s.clear(),s.insert(1e9);
int yjy=-2e9;
for(int i=1; i<=cnt; i++)
{
if(p[i].t==1) s.insert(p[i].y);
if(p[i].t==2) s.erase(p[i].y);
if(p[i].t==-1) yjy=sy;
if(yjy>-2e9)
{
it=s.lower_bound(yjy);
yjy=*it;
}
if(p[i].t==-2)
{
if(yjy<ty) return;
break;
}
}
sort(a+1,a+1+n,cmp);
t.clear(),t.insert(ND(sy,0));
for(int i=1; i<=n; i++) if(a[i].x1>sx)
{
if(a[i].x1>tx) break;
it0=t.lower_bound(ND(a[i].y1,0));
int mi0=2e9,mi1=2e9;
while(it0!=t.end()&&(*it0).x<=a[i].y2)
{
mi0=min(mi0,(*it0).d+(*it0).x-a[i].y1);
mi1=min(mi1,(*it0).d+a[i].y2-(*it0).x);
it1=it0,it0++,t.erase(it1);
}
if(mi0<2e9)
{
t.insert(ND(a[i].y1,mi0));
t.insert(ND(a[i].y2,mi1));
}
}
for(it0=t.begin(); it0!=t.end(); it0++)
ans=min(ans,abs((*it0).x-ty)+(*it0).d+tx-sx);
}
int main()
{
freopen("travel.in","r",stdin); freopen("travel.out","w",stdout);
scanf("%d%d%d%d%d",&n,&sx,&sy,&tx,&ty);
for(int i=1; i<=n; i++) scanf("%d%d%d%d",&a[i].x1,&a[i].y1,&a[i].x2,&a[i].y2);
int t1,t2;
if(sx>tx) t1=-1; else t1=1;
if(sy>ty) t2=-1; else t2=1;
sx*=t1,tx*=t1,sy*=t2,ty*=t2;
for(int i=1; i<=n; i++)
{
a[i].x1*=t1,a[i].x2*=t1,a[i].y2*=t2,a[i].y1*=t2;
if(a[i].x1>a[i].x2) swap(a[i].x1,a[i].x2);
if(a[i].y1>a[i].y2) swap(a[i].y2,a[i].y1);
}
ans=2e9;
solve();
swap(sx,sy),swap(tx,ty);
for(int i=1; i<=n; i++) swap(a[i].x1,a[i].y1),swap(a[i].x2,a[i].y2);
solve();
printf("%d",ans);
}