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].
1 #include<bits/stdc++.h> 2View Codeusing 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 }
ARC072E Alice in linear land