USACO 2015 US OPEN Gold T3: Trapped in the Haybales

题目大意

农夫约翰最近买了N(1N100,000)个干草堆,他把这些干草堆都放在家和农场之间的一条直路上,每个干草堆的位置各不相同。不幸的是,他忘记了他的奶牛贝里斯正外出吃草,贝里斯也许会被这些干草堆所限制住!干草堆j的大小是Sj,在Pj的位置上。贝里斯从一个不是干草堆的地方出发,他可以自由的在这条直线上移动,他不能越过干草堆。有一种特殊的情况, 他可以往一个方向连续跑了D的距离以后,他就可以积累足够的能量,然后就可以消除小于D的干草堆。当然了,在消除了一个干草堆以后,他就可以有更多的空间来跑步和积蓄能量了。当贝里斯成功消除了第一个或者最后一个干草堆的时候,他就可以获得自由了,请你计算使得贝里斯不能获得自由的初始位置的区间总和。

题目分析

观察题目,可以想到对于一段区间 i,模拟以区间 i 为起点并试图逃脱的过程,如果可以到达入一段已经判断为可以逃脱的区间 j ,那么区间 i 也是可以逃脱的。

这样我们可以从 1 到 n-1 枚举 i(第 i 段区间),用 l, r 记录这段区间目前所能到达最左边的草堆与最右边的草堆。

每次模拟消除草堆的过程,直到在当前 l, r 中无法消除 l与r 草堆 或 l==0 或 r==n 或 到达了一段可以逃脱的区间。这样复杂度几乎是 O(N)的。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int MAXN=1e5+10;
 4 
 5 struct Node{
 6     int hei,pos;
 7 }a[MAXN];
 8 inline bool cmp(Node x,Node y){
 9     return x.pos<y.pos;
10 }
11 
12 int n,ans,len,l,r;
13 bool f[MAXN],flag;
14 inline bool Check(int x){
15     len=a[x+1].pos-a[x].pos;
16     l=x;r=x+1;
17     while(1<=l&&r<=n){
18         flag=false;
19         if(len>a[l].hei){
20             flag=1;
21             --l;
22             if(f[l]){
23                 f[x]=true;
24                 return true;
25             }
26             len+=(a[l+1].pos-a[l].pos);
27         }
28         if(len>a[r].hei){
29             flag=1;
30             ++r;
31             if(f[r-1]){
32                 f[x]=1;
33                 return true;
34             }
35             len+=(a[r].pos-a[r-1].pos);
36         }
37         if(!flag) return false;
38     }
39     return true;
40 }
41 int main(){
42     scanf("%d",&n);
43     for(int i=1;i<=n;++i)
44         scanf("%d%d",&a[i].hei,&a[i].pos);
45     sort(a+1,a+n+1,cmp);
46     f[0]=1;f[n]=1;
47     for(int i=1;i<n;++i)
48         if(!Check(i))
49             ans+=a[i+1].pos-a[i].pos;
50     printf("%d\n",ans);
51     return 0;
52 }

 

posted @ 2019-07-19 17:05  LI_dox  阅读(245)  评论(0编辑  收藏  举报