Best Cow Fences POJ - 2018

原题链接

考察:二分

再做一次还是没想到系列 蒟蒻本蒻

思路:

        这道题的check函数很好想,就是枚举端点,找到区间>=l&&平均值>=mid的区间.暴力枚举是sum[j]-sum[i]>=(j-i)*mid.我们需要进行优化,要将二重循环优化到一维,i必须省去,我们求[i,j]区间是否平均值>=mid,转化为sum[i,j]-(j-i)*mid>=0,而这相当于在[i,j]区间内每个元素都-=mid,最后看是否>=0.省去(j-i)*mid,我们还要考虑如何优化掉sum[i],可以发现随着右端点不断延伸,左端点可取值是连续增加的(如果枚举左端点就是不断减少),根据此性质可以动态求出最小值,只要看sum[j]-mins>=0即可.

 1 #include <iostream>
 2 #include <cstring>
 3 #include <cstdio>
 4 #include <algorithm>
 5 using namespace std;
 6 typedef long long LL;
 7 const int N = 100010;
 8 const double eps = 1e-5; 
 9 int n,f,maxn,a[N];
10 double b[N];
11 bool check(double s)
12 {
13     for(int i=1;i<=n;i++) b[i] = a[i]-s,b[i]+=b[i-1];
14     double tmp = 0;
15     for(int i=f,j=0;i<=n;i++)
16     {
17         tmp = min(tmp,b[j]),j++;
18         if(b[i]-tmp>=0) return 1;
19     }
20     return 0;
21 }
22 int main()
23 {
24     scanf("%d%d",&n,&f);
25     for(int i=1;i<=n;i++) scanf("%d",&a[i]),maxn = max(maxn,a[i]);
26     double l = 0,r = maxn;
27     while(r-l>eps)
28     {
29         double mid = (r+l)/2;
30         if(check(mid)) l = mid;
31         else r = mid;
32     }
33     int ans = r*1000;
34     printf("%d\n",ans);
35     return 0;
36 }

 

2021.6.23 大草,再做一次还是没做出来,前缀和数组没有递增或递减的性质,没想出来怎么求>=f的区间的最大差是否>=0.这里的骚操作是求左端点区间内的最小值.没想到啊我太菜了.

posted @ 2021-03-06 15:29  acmloser  阅读(45)  评论(0编辑  收藏  举报