51 Nod 1281 山峰和旗子 (二分)

                               1281 山峰和旗子
用一个长度为N的整数数组A,描述山峰和山谷的高度。山峰需要满足如下条件, 0 < P < N - 1 且 A[P - 1] < A[P] > A[P + 1]。
 
 
现在要在山峰上插上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

思路:思路简单
   把所有山峰找出来 最后一个不能算!!! (因为右边没有比他小的山)
   当然第一个也不能算
   每次二分一个 mid 表示要插 mid 个旗子 检验是否可行
   大佬竟然dp检验!! 我只会模拟检验了。。
 1 #include <cstdio>
 2 #include <cctype>
 3 #include <algorithm>
 4 #define max(a,b) a<b?b:a
 5 
 6 const int MAXN=50010;
 7 
 8 int n,tot;
 9 
10 int a[MAXN],b[MAXN];
11 
12 inline void read(int&x) {
13     int f=1;register char c=getchar();
14     for(x=0;!isdigit(c);c=='-'&&(f=-1),c=getchar());
15     for(;isdigit(c);x=x*10+c-48,c=getchar());
16     x=x*f;
17 }
18 
19 bool check(int x) {
20     int t=0,s=1;
21     for(int i=2; i<=tot; ++i) {
22         t+=b[i]-b[i-1];
23         if(t>=x) ++s,t=0;
24     }
25     if(s>=x) return true;
26     return false;
27 }
28 
29 int hh() {
30     read(n);
31     for(int i=1; i<=n; ++i) read(a[i]);
32     for(int i=2; i<n; ++i) if(a[i]>a[i-1] && a[i]>a[i+1]) b[++tot]=i;
33     
34     int l=0,r=tot+1;
35     while(l+1<r) {
36         int mid=(l+r)>>1;
37         if(check(mid)) l=mid;
38         else r=mid;
39     }
40     
41     printf("%d\n",l);
42     return 0;
43 }
44 
45 int sb=hh();
46 int main(int argc,char**argv) {;}
View Code

 

 
 
posted @ 2017-10-24 20:15  拿叉插猹哈  阅读(301)  评论(0编辑  收藏  举报