LA 3177 二分

 1 /*
 2 LA 3177
 3 《训练指南》
 4 思维的考察,积累下来,锻炼思维感。
 5 */
 6 #include <iostream>
 7 #include <cmath>
 8 #include <algorithm>
 9 #include <string.h>
10 #include <stdio.h>
11 #include <set>
12 #include <stack>
13 #include <vector>
14 #define maxn 100010
15 #define INF 999999999
16 using namespace std;
17 
18 int lf[maxn],rg[maxn];
19 int N,L,R;
20 int r[maxn];
21 bool isok(int k){//测试k个是否可以
22     //固定坐标
23     int ll=r[1],rr=k-r[1];
24     lf[1]=r[1];rg[1]=0;
25     for(int i=2;i<=N;i++){
26         if (i % 2 == 1){
27             rg[i]=min(r[i],rr-rg[i-1]);//本身要放的个数,右边剩下的空位
28             lf[i]=r[i]-rg[i];//剩下的肯定都放在左边
29         }
30         if (i % 2 == 0){//尽量在1号划分的区间的左边放置
31             lf[i]=min(r[i],ll-lf[i-1]);
32             rg[i]=r[i]-lf[i];
33         }
34     }
35     //判断1和n是否有重合的部分
36     //偶数号向前取,奇数号向后取,才能更可能达成下面的条件
37     if (lf[N]==0) return true;else return false;
38 }
39 void solve(){
40 //    cout<<L<<","<<R<<endl;
41     if (N==1) {//一定要记得测试小数据
42         printf("%d\n",r[1]);
43         return ;
44     }
45     if (N % 2 == 0) {
46         printf("%d\n",L);
47         return ;
48     }
49     while(L<R){
50         int M=L+(R-L)/2;//开始时二分写错了
51         if (!isok(M)) L=M+1;else R=M;
52     }
53     printf("%d\n",L);
54 }
55 int main(){
56     while(~scanf("%d",&N) && N){
57         L=-1,R=-1;
58         for(int i=1;i<=N ;i++){
59             scanf("%d",&r[i]);
60         }
61         r[N+1]=r[1];
62         for(int i=1;i<=N;i++){
63             L=max(L,r[i]+r[i+1]);
64             R=max(R,r[i]*3);//这个值最终肯定会等于最大的r的3倍,那么左中右三个都会分配到
65         }
66         solve();
67     }
68     return 0;
69 }

 

posted @ 2014-04-07 11:06  little_w  阅读(276)  评论(0编辑  收藏  举报