LA 3177 长城守卫

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 }
代码君
原文地址:https://www.cnblogs.com/AOQNRMGYXLMV/p/3886428.html