码迷,mamicode.com
首页 > 其他好文 > 详细

[UVa 1335]Beijing Guards

时间:2017-09-18 22:34:28      阅读:219      评论:0      收藏:0      [点我收藏+]

标签:下界   偶数   size   重复   二分   def   hellip   i++   for   

技术分享

题解

拿到题,没什么头绪,我们模拟一下,很容易得出一个结论:

如果$n$为偶数,那么答案就是$max(r[i]+r[i+1])$。具体方案就是,如果$i$为奇数,那么取$[1,r[i]]$;若$i$为偶数,则取$[ans-r[i]+1,ans]$。

同样我们此时的$ans$是答案的下界。

可当$n$为奇数时,我们这样贪心策略出现问题就是由于$1$和$n$都是奇数,会取$[1,r[1]]$,$[1,r[n]]$显然会重复,那么奇数我们就不能这样做了。

我们由$n$为偶数的思想,我们还是让$1$号取$[1,r[1]]$,那么就要让$n$尽量往“后”取,这样$n-1$就要尽量往“前”取……

因此我们得出“除$1$以外奇数往后取,偶数往前取”,那么我们只需要通过假定的$ans$值,做一遍模拟即可。

对于如何选取$ans$,我们可以去二分。

另外一个方面,我们发现我们不需要知道我们到底是取了哪些值,我们最后只要知道是不是第$n$个人取了$[1,r[1]]$的数。那么我们把所有的数分为$[1,r[1]]$和$[r[1],ans]$两个区间,我们在区间内讨论即可。

另外:注意$n == 1$的时候的特判,因为这个$wa$了很多次。

 1 //It is made by Awson on 2017.9.18
 2 #include <map>
 3 #include <set>
 4 #include <cmath>
 5 #include <ctime>
 6 #include <queue>
 7 #include <stack>
 8 #include <cstdio>
 9 #include <string>
10 #include <vector>
11 #include <cstdlib>
12 #include <cstring>
13 #include <iostream>
14 #include <algorithm>
15 #define LL long long
16 #define Max(a, b) ((a) > (b) ? (a) : (b))
17 #define Min(a, b) ((a) < (b) ? (a) : (b))
18 #define Abs(a) ((a) < 0 ? (-(a)) : (a))
19 using namespace std;
20 const int N = 100000;
21 
22 int n, r[N+5];
23 
24 bool judge(int p) {
25     int Left[N+5] = {0}, Right[N+5] = {0};
26     int x = r[1], y = p-r[1];
27     Left[1] = x;
28     for (int i = 2; i <= n; i++) {
29         if (i%2) {
30             Right[i] = Min(y-Right[i-1], r[i]);
31             Left[i] = r[i]-Right[i];
32         }
33         else {
34             Left[i] = Min(x-Left[i-1], r[i]);
35             Right[i] = r[i]-Left[i];
36         }
37     }
38     return Left[n] == 0;
39 }
40 void work() {
41     int L = 0, R = 0;
42     for (int i = 1; i <= n; i++)
43         scanf("%d", &r[i]);
44     if (n == 1) {
45         printf("%d\n", r[1]);
46         return;
47     }
48     r[n+1] = r[1];
49     r[n+2] = r[2];
50     for (int i = 1; i <= n; i++) {
51         L = Max(L, r[i]+r[i+1]);
52         R = Max(R, r[i]+r[i+1]+r[i+2]); 
53     }
54     if (!(n%2))
55         printf("%d\n", L);
56     else {
57         int ans = R;
58         while (L <= R) {
59             int mid = (L+R) >> 1;
60             if (judge(mid)) R = mid-1, ans = mid;
61             else L = mid+1;
62         }
63         printf("%d\n", ans);
64     }
65 }
66 
67 int main() {
68     while ((~scanf("%d", &n)) && n)
69         work();
70     return 0;
71 }

 

[UVa 1335]Beijing Guards

标签:下界   偶数   size   重复   二分   def   hellip   i++   for   

原文地址:http://www.cnblogs.com/NaVi-Awson/p/7544892.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!