Uva 长城守卫——1335

二分查找+一定的技巧

 1 #include<iostream>
 2 using namespace std;
 3 
 4 const int maxn=100000+10;
 5 int n,r[maxn],Left[maxn],Right[maxn];//因为不用计算方案,所以可以按【1~r[i]】和【r[i]+1~p】中各拿几个分,当时没想到这个用set类写了个超耗时间的~~~~(>_<)~~~~ 
 6 
 7 bool ok(int p)
 8 {
 9     int x=r[1],y=p-r[1];
10     Left[1]=x;Right[1]=0;
11     for(int i=2;i<=n;i++)
12     {
13         if(i&1)
14         {
15             Right[i]=min(y-Right[i-1],r[i]);//奇数守卫先拿右边
16             Left[i]=r[i]-Right[i];//再看左边要几个
17         }
18         else
19         {
20             Left[i]=min(x-Left[i-1],r[i]);//偶数守卫先拿左边
21             Right[i]=r[i]-Left[i];//再看右边要几个
22         }
23     }
24     return Left[n]==0;//第n个守卫左边为0时
25 }
26 
27 int main()
28 {
29     while(cin>>n&&n)
30     {
31         for(int i=1;i<=n;i++)
32             cin>>r[i];
33         if(n==1) {cout<<r[1]<<endl;continue;}//这个地方坑了我
34         r[n+1]=r[1];
35         int L=0,R=0;
36         for(int i=1;i<=n;i++) L=max(L,r[i]+r[i+1]);
37         if(n&1)
38         {
39             for(int i=1;i<=n;i++) R=max(R,r[i]*3);
40             while(L<R)
41             {
42                 int M=(L+R)/2;
43                 if(ok(M)) R=M;
44                 else L=M+1;
45             }
46         }
47         cout<<L<<endl;
48     }
49 }
原文地址:https://www.cnblogs.com/InWILL/p/5585888.html