n为偶数的时候比较简单,就是相邻两个守卫的礼物和的最大值。
首先这是个下限,其次这个值也满足题目要求,所以这就是答案了。
当n为奇数的时候上限是守卫索要礼物的最大值的三倍。
这也很容易理解,比如n=5,ri都为1的时候,每个人拿到的礼物是1,2,1,2,3
有了上限有了下限就可以二分找出答案来了。
test函数的作用就是测试p种礼物能否满足要求。
1 //#define LOCAL 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 7 const int maxn = 100000 + 10; 8 int n, r[maxn], left[maxn], right[maxn]; 9 10 bool test(int p) 11 { 12 int x = r[1], y = p - x; 13 left[1] = x; right[1] = 0; 14 for(int i = 2; i <= n; ++i) 15 { 16 if(i & 1 == 1) 17 {//奇数尽量往后取 18 right[i] = min(r[i], y - right[i-1]); 19 left[i] = r[i] - right[i]; 20 } 21 else 22 {//偶数则尽量往前取 23 left[i] = min(r[i], x - left[i-1]); 24 right[i] = r[i] - left[i]; 25 } 26 } 27 return (left[n] == 0); 28 } 29 30 int main(void) 31 { 32 #ifdef LOCAL 33 freopen("3177in.txt", "r", stdin); 34 #endif 35 36 while(scanf("%d", &n) && n) 37 { 38 int i; 39 for(i = 1; i <= n; ++i) 40 scanf("%d", &r[i]); 41 if(n == 1) 42 { 43 printf("%d ", r[1]); 44 continue; 45 } 46 int L = 0, R = 0; 47 r[n+1] = r[1]; 48 for(i = 1; i <= n; ++i) 49 L = max(L, r[i]+r[i+1]); 50 if(n%2 == 1) 51 { 52 for(i = 1; i <= n; ++i) 53 R = max(R, r[i]); 54 R *= 3; 55 while(L < R) 56 { 57 int mid = (L + R) / 2; 58 if(test(mid)) 59 R = mid; 60 else 61 L = mid + 1; 62 } 63 } 64 printf("%d ", L); 65 } 66 return 0; 67 }