LibreOj-10012-「一本通-1-2-例-2」Best-Cow-Fences

题目地址

思路

二分平均值,区间为$0$~$2000$。将每个$a[i]$减去平均值,就只用考虑字段和是否$>=0$了。 关于计算子段和,可以使用前缀和表示,$sum[i]$表示前$i$个数的和。 由$L$~$n$以循环子段的尾巴,关于每次循环: * 维护一个子段开头的最小值 * 找到这个平均值中,最大的子段和 **注意:**由于是$*1000$的$int$结果,自然是保留到5位小数(4+1进位),故二分判断为$r-l>1e-5$。 ```cpp #include #include #include using namespace std; double sum[100001]; int n,L,a[100001]; int main() { scanf("%d%d",&n,&L); for(int i=1;i<=n;i++)scanf("%d",a+i); double l=0,r=2000,eps=1e-5; while(r-l>eps){ double mid=(l+r)/2; for(int i=1;i<=n;i++)sum[i]=sum[i-1]+a[i]-mid; double ans=-1e10,min_v=1e10; for(int i=L;i<=n;i++){ min_v=min(min_v,sum[i-L]); ans=max(ans,sum[i]-min_v); } if(ans>=0)l=mid; else r=mid; } printf("%d",int(r*1000)); } ```
原文地址:https://www.cnblogs.com/dmoransky/p/10742642.html