题意是描述是这样的,给你n个围栏,对于每个围栏你必须走到其边上才可以往下跳,现在问你从初始最高位置的n个围栏,到原点,水平走过的路程最少是多少?
其实我可可以这样来考虑问题。由于每次都是从板子的左右两端往下面跳,我们可以从1到n有序的加入每一块板子(相当于对区间染色),加入每块板子查询一下它的两端的下面的点是什么。有了这个操作我们就可以直接预处理出来从每一块板子左右两端跳下来会落在那一块板子上面。
那应该用什么办法来实现这个查询和更新呢?显然,线段树。
下面我们等于是分别从第n块板子的左右端点往下走,然后求到原点的水平最短路了,直接一遍SPFA搞定。
上代码吧,下面省略若干个字。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <queue> 5 #define maxn 200100 6 using namespace std; 7 8 const int add=100005; 9 int n,S,ans; 10 int l[maxn],r[maxn],fl[maxn],fr[maxn],pl[maxn],pr[maxn]; 11 int a[4*maxn],col[4*maxn]; 12 bool inq[maxn]; 13 14 int abs(int x) 15 { 16 return x>=0?x:-x; 17 } 18 19 void PushDown(int rt) 20 { 21 if (col[rt]==-1) return; 22 col[rt<<1]=col[rt<<1|1]=col[rt]; 23 col[rt]=-1; 24 } 25 26 void update(int rt,int l,int r,int L,int R,int id) 27 { 28 if (L<=l && R>=r) 29 { 30 col[rt]=id; 31 return; 32 } 33 PushDown(rt); 34 int mid=(l+r)>>1; 35 if (L<=mid) update(rt<<1,l,mid,L,R,id); 36 if (R> mid) update(rt<<1|1,mid+1,r,L,R,id); 37 } 38 39 int query(int rt,int l,int r,int pos) 40 { 41 if (l<=pos && r>=pos && col[rt]>=0) return col[rt]; 42 PushDown(rt); 43 int mid=(l+r)>>1; 44 if (pos<=mid) return query(rt<<1,l,mid,pos); 45 else return query(rt<<1|1,mid+1,r,pos); 46 } 47 48 void bfs() 49 { 50 fl[n]=S-l[n],fr[n]=r[n]-S; 51 queue<int> Q; 52 Q.push(n); 53 while (!Q.empty()) 54 { 55 int cur=Q.front(); 56 Q.pop(),inq[cur]=false; 57 int next1=pl[cur],next2=pr[cur]; 58 59 if (next1==0) ans=min(ans,fl[cur]+abs(add-l[cur])); 60 else 61 { 62 if (fl[cur]+l[cur]-l[next1]<fl[next1] || fl[cur]+r[next1]-l[cur]<fr[next1]) 63 { 64 fl[next1]=min(fl[next1],fl[cur]+l[cur]-l[next1]); 65 fr[next1]=min(fr[next1],fl[cur]+r[next1]-l[cur]); 66 if (!inq[next1]) Q.push(next1),inq[next1]=true; 67 } 68 } 69 70 if (next2==0) ans=min(ans,fr[cur]+abs(add-r[cur])); 71 else 72 { 73 if (fr[cur]+r[cur]-l[next2]<fl[next2] || fr[cur]+r[next2]-r[cur]<fr[next2]) 74 { 75 fl[next2]=min(fl[next2],fr[cur]+r[cur]-l[next2]); 76 fr[next2]=min(fr[next2],fr[cur]+r[next2]-r[cur]); 77 if (!inq[next2]) Q.push(next2),inq[next2]=true; 78 } 79 } 80 } 81 } 82 83 int main() 84 { 85 //while (scanf("%d%d",&n,&S)!=EOF) 86 { 87 scanf("%d%d",&n,&S); 88 S+=add; 90 memset(fl,0x3f,sizeof fl); 91 memset(fr,0x3f,sizeof fr); 92 for (int i=1; i<=n; i++) 93 { 94 scanf("%d%d",&l[i],&r[i]); 95 l[i]+=add,r[i]+=add; 96 pl[i]=query(1,1,maxn,l[i]); 97 pr[i]=query(1,1,maxn,r[i]); 98 update(1,1,maxn,l[i],r[i],i); 99 } 100 ans=~0U>>2; 101 bfs(); 102 printf("%d ",ans); 103 } 104 return 0; 105 }