http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1281

题目来源: Codility
基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题
51nod 1281 二分_数组_02 收藏
51nod 1281 二分_最优解_03 关注
用一个长度为N的整数数组A,描述山峰和山谷的高度。山峰需要满足如下条件, 0 < P < N - 1 且 A[P - 1] < A[P] > A[P + 1]。
 
51nod 1281 二分_c++_04
 
现在要在山峰上插上K个旗子,并且每个旗子之间的距离 >= K,问最多能插上多少个旗子(即求K的最大值)。两个山峰之间的距离为|P - Q|。
以上图为例,高度为:1 5 3 4 3 4 1 2 3 4 6 2。其中可以作为山峰的点为:1 3 5 10。
 
放2面旗子, 可以放在1 和 5。
放3面旗子, 可以放在1 5 和 10。
放4面旗子, 可以放在1 5 和 10,之后就放不下了。
所以最多可以放3面旗子。
Input
第1行:一个数N,表示数组的长度(1 <= N <= 50000)。
第2 - N + 1行:每行1个数Ai(1 <= Ai <= 10^9)。
Output
输出最多能插上多少面旗子(即求K的最大值)。
Input示例
12
1 
5 
3 
4 
3 
4 
1 
2 
3 
4 
6 
2
Output示例
3

显然可以枚举K值,至于判断K是否可行,把第一个山峰看作必放旗子然后往后贪心遇见可以放的位置就放就能找到最大的可放置旗子数,形如时间安排的证明过程假设最优解不包含第一个山峰,会发现第一个山峰包含显然优于不包含。
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int h[50005];
 4 vector<int>vi;
 5 bool ok(int k)
 6 {
 7     int s=1,pre=vi[0];
 8     for(int i=1;i<vi.size();++i)
 9     {
10         if(vi[i]-pre>=k){
11             s++;
12             pre=vi[i];
13         }
14     }
15     if(s>=k) return 1;
16     return 0;
17 }
18 int main()
19 {
20     int N,i,j;
21     cin>>N;
22     for(i=1;i<=N;++i) scanf("%d",h+i);
23     for(i=2;i<N;++i)
24         if(h[i]>h[i-1]&&h[i]>h[i+1]) vi.push_back(i);
25     int l=0,r=vi.size();
26     while(l<r){
27         int mid=r-(r-l)/2;
28         if(ok(mid)) l=mid;
29         else r=mid-1;
30     }
31     cout<<l<<endl;
32     return 0;
33 }