ARC072E Alice in linear land
题解:
首先我们要观察到一个性质,因为在固定的起始距离下,经过固定的操作,最后所在的位置是固定的,我们设经过操作1 ~ i之后所在的地方距离终点为d[i].
那么如果女巫可以修改第i个操作,那么就相当于已经经过了1 ~ i - 1的操作,所以这个时候Alice已经在d[i - 1]的位置了,那么这个时候女巫可以通过修改s[i]来使得Alice和终点的距离减小,因为如果一个s[i]可以使得距离缩小,那么Alice一定会走,因此Alice的下一位置将是[0, d[i - 1]]中的任意位置。
我们设f[i]表示最小的起始距离x使得经过i ~ n的操作无法到达终点。
那么显然如果f[i + 1] <= d[i - 1],女巫就一定可以使得Alice无法到达终点。
因此考虑如何转移。
首先f[n + 1]表示不经过任何操作,那么这个时候的最小距离显然是1.
考虑加入一个操作s[i]。
1,如果当前在f[i + 1] 并且 s[i]这个操作不会被执行,那么s[i]就不会对f[i]造成影响,所以最近的距离还是f[i + 1]。
那么什么时候s[i]不会被执行?显然s[i]需要 >= f[i + 1]并使得s[i] - f[i + 1] >= f[i + 1],移项得到f[i + 1] <= s[i] / 2.
2,如果这个操作被执行,那么将会缩短与目的地的距离,因为经过f[i + 1]的操作,最小的无法到达目的地的距离为f[i + 1],
而原本在f[i + 1]的Alice经过s[i]这个操作缩短了与目的地的距离后,距离已经小于f[i + 1]了,因此这个时候肯定是可以到达目的地了。
而为了使f[i]尽可能小,所以肯定要使得f[i]经过操作s[i]后到达f[i + 1],因为f[i + 1]是经过操作i + 1 ~ n最小的无法到达目的地的距离,不能再更小了。
因此f[i] = f[i + 1] + s[i].
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define R register int 4 #define AC 501000 5 #define LL long long 6 7 int n, m; 8 int s[AC], d[AC], f[AC]; 9 10 inline int read() 11 { 12 int x = 0;char c = getchar(); 13 while(c > '9' || c < '0') c = getchar(); 14 while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); 15 return x; 16 } 17 18 void pre() 19 { 20 n = read(), d[0] = read(); 21 for(R i = 1; i <= n; i ++) 22 { 23 s[i] = read(), d[i] = d[i - 1]; 24 if(d[i] >= s[i]) d[i] -= s[i]; 25 else if(s[i] - d[i] < d[i]) d[i] = s[i] - d[i]; 26 } 27 } 28 29 void work()//f[i]表示经过操作i ~ n,使得Alice无法到达终点的最小起始距离x 30 { 31 f[n + 1] = 1; 32 for(R i = n; i; i --) 33 if(f[i + 1] <= s[i] / 2) f[i] = f[i + 1]; 34 else f[i] = f[i + 1] + s[i]; 35 m = read(); 36 for(R i = 1; i <= m; i ++) 37 { 38 int x = read(); 39 if(d[x - 1] >= f[x + 1]) printf("YES\n"); 40 else printf("NO\n"); 41 } 42 } 43 44 int main() 45 { 46 freopen("in.in", "r", stdin); 47 pre(); 48 work(); 49 fclose(stdin); 50 return 0; 51 }