用下面这个图辅助说明
这题只需要从上到下按层 维护图中这些虚线即可。
例如当前需要在图中红栏杆处做决策时,需要把上面的三条虚线删除,而添加两端点处的新路径,路程当然要去上面三条路的最小值 。
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
using namespace std;
const int maxn=50050 , INF = 0x7f7f7f7f;
map<int,int>DP;
typedef map<int ,int>::iterator MIT;
int L[maxn] , R[maxn] , N, S;
int readint(){
char c=getchar();
int ans = 0 ,t=1;
while((c<'0' || c>'9') && c != '-') c=getchar();
if(c=='-') {t=-1; c=getchar(); }
while(c>='0' && c<='9') ans= ans*10 + c-'0' , c=getchar();
return ans*t;
}
int main()
{
while(scanf("%d%d",&N,&S)!=EOF){
DP.clear();
for(int i=N; i>=1; i--)
L[i] = readint() , R[i] = readint();
//scanf("%d%d",&L[i],&R[i]);
DP[S]=0;
for(int i=1;i<=N;i++){
MIT Begin = DP.lower_bound(L[i]+1) , End = DP.lower_bound(R[i]);
if(Begin==End) continue;
int ML=INF , MR = INF;
for(MIT it=Begin; it!=End ; it++){
ML = min(ML , it->second + it->first-L[i]);
MR = min(MR , it->second + R[i]-it->first);
}
DP.erase(Begin,End);
if(DP.count(L[i])) DP[L[i]] = min (DP[L[i]] , ML);
else DP[L[i]] = ML;
if(DP.count(R[i])) DP[R[i]] = min(DP[R[i]] , MR);
else DP[R[i]] = MR;
}
int ans = INF;
for(MIT it=DP.begin(); it!=DP.end() ; it++){
ans = min(ans , it->second + abs(it->first));
}
printf("%d\n",ans);
}
return 0;
}