• poj2018 Best Cow Fences 题解报告


    题目传送门

    【题目大意】

    有$N$块土地,第$i$块土地有$A_i$头牛,选出连续的至少$F$块土地,使得平均每块土地上牛的数量最大。

    【思路分析】

    二分转化求值为判定,即二分出平均数$mid$,判定“是否存在一个长度不小于$F$的子段,子段和非负”。这题有一点特殊的地方就是有长度限制,对于子段和,我们可以用前缀和解决,首先想到可以这样:

    $$max{sum_i-min{sum_j}(0le jle i-F)}(Fle i<n)$$

    但是这样复杂度太大,所以我们要考虑如何简化。发现随着$i$的增长,$j$的取值范围每次只会增大1,即每次只会有一个新的值进入候选集合$min{sum_j}$,所以没有必要每次循环枚举$j$,只要用一个变量记录当前最小值,每次与新的取值取$min$就可以了。

    【代码实现】

     1 #include<cstdio>
     2 #include<iostream>
     3 #define rg register
     4 #define go(i,a,b) for(rg int i=a;i<=b;i++)
     5 using namespace std;
     6 const int N=100002;
     7 double a[N],s[N],b[N];
     8 int n,f;
     9 int main(){
    10     scanf("%d%d",&n,&f);double maxn=0;
    11     go(i,1,n) scanf("%lf",&a[i]),maxn=max(maxn,a[i]);
    12     double l=s[n]/n,r=(double)maxn;
    13     while(r-l>1e-5){
    14         double mid=(l+r)/2;
    15         go(i,1,n) b[i]=a[i]-mid,s[i]=s[i-1]+b[i];
    16         double ans=-N,minn=N;
    17         go(i,f,n){
    18             minn=min(minn,s[i-f]);
    19             ans=max(ans,s[i]-minn);
    20         }
    21         if(ans>=0) l=mid;else r=mid;
    22     }
    23     cout<<int(r*1000)<<endl;
    24     return 0;
    25 }
    代码戳这里
  • 相关阅读:
    不要试图给Password类型的TextBox赋值!
    asp.net与javacript之间的通讯
    这个iframe有点奇怪
    C#的异常处理机制 (转载)
    公匙算法.电子签名
    西煞魄工厂的入门教程
    Web services and SOAP
    观察者模式
    WebService:使用 Soap 标头自定义身份验证和授权(转载)
    社会型网络(3)-回到现实(转载)
  • 原文地址:https://www.cnblogs.com/THWZF/p/11248002.html
Copyright © 2020-2023  润新知