最佳牛围栏

Posted a1b3c7d9

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了最佳牛围栏相关的知识,希望对你有一定的参考价值。

最佳牛围栏

给出长度为n数列\\(\\a_i\\\\),求其中的一段子段的平均数的最大值,并且保证子段长度大于等于f,\\(1≤n≤100000\\)

[警告:此题卡精度]

法一:二分

这是一道有关单调性的问题,不太好二分,可考虑写出二分式,不妨记最优解为\\(\\barx\\),那么对于最优解有

\\[\\frac\\sum_i=l^ra_ir-l+1=\\barx\\]

经过式子变换有其二分式

\\[\\sum_i=l^r(a_i-\\barx)=0\\]

于是只要判断左式答案与0的关系,就可以确定是否有最优解了,当左式的最大值大于0时,我们就可以知道\\(\\barx\\)可以更加优秀,反之,于是问题变成如何求左式的最大值,不妨构造新数列\\(\\b_i\\\\),有\\(b_i=a_i-\\barx\\),现在问题转化为求数列\\(\\b_i\\\\)的最大子段和

我们自然想到原来的贪心模型,从数列左向右确定子段的右端点,当右端点到了某个位置事子段和小于0时,左端点从此处令起。

但是此题有长度限制,注意到原问题也可以看成区间问题,于是枚举右端点r,再枚举左端点l的上一个位置,不妨记\\(\\B_i\\\\)\\(\\b_i\\\\)前缀和,于是所求最大值即\\(s_r-s_l\\),注意到在枚举右端点r时,\\(s_r\\)为定值,只要寻找到\\(s_l\\)的最小值即可,每次r向右移,就增加一个决策点,只要用一个变量保存最优解,每次和新进来的决策点比较取大小即可。

参考代码:

#include <iostream>
#include <cstdio>
#define il inline
#define ri register
#define lb double
#define exact 0.00001
#define intmax 0x7fffffff
using namespace std;
lb b[100001];
int a[100001],n,f;
template<class free>
il free Max(free,free);
il bool check(lb);
int main()
    scanf("%d%d",&n,&f);
    for(int i(1);i<=n;++i)
        scanf("%d",&a[i]);
    lb l(1),r(2000),mid;
    while(l+exact<=r)
        mid=(l+r)/2;
        if(check(mid))l=mid;
        else r=mid;
    printf("%d",(int)(r*1000));
    return 0;

template<class free>
il free Max(free a,free b)
    return a>b?a:b;

il bool check(lb x)
    for(int i(1);i<=n;++i)
        b[i]=a[i]-x,b[i]+=b[i-1];
    int l(0);lb ans(-intmax);
    for(int r(f);r<=n;++r)
        ans=Max(ans,b[r]-b[l]);
        if(b[r-f+1]<b[l])l=r-f+1;
    return ans>=0;

法二:斜率优化

\\(f_i\\)为前i个数的最优解,显然有

\\[f_i=\\max_0\\leq j<i\\\\fracs_i-s_ji-j\\\\]

注意到这个类似斜率的东西,先考虑单调性,其中\\(j,s_j\\)显然是单调递增的,至于\\(f_i\\)未知,于是问题可以转化成求点\\((i,s_i)\\)与点集\\(\\(j,s_j)\\\\)的一个点所连的一条直线的斜率最大值

对于任意三个点A,B,C考虑,设A,B是决策点,C与i有关,即\\((i,s_i)\\),按照当初推出凸壳的方法,对于任意三个点考虑,只有下图两种情况

技术图片

对于该图,容易知道决策点取点B比A更优秀,我们不妨将它叫做下凸三角形(多形象啊),特点在\\(k_AB<k_BC\\)

技术图片

对于该图,容易知道决策点A比B更加优秀,我们不妨将它叫做下凸三角形,特点为\\(K_AB>K_AC\\)

(注:根据两幅图的总结,更加本质的性质即c是否在直线AB的上方)

而这只能告诉我们任意三个点中哪个决策点会更加优秀,不能推广到大量的点,于是我们的找一个图形的载体维护,使能够成为最优决策点的答案都在上面,自然想到凸壳,用单调队列维护一个下凸壳。

技术图片

当B成为最优秀决策点的时候,那么根据前面两幅图的规律,我们应该队首弹出A点,而根据凸壳的规律后面的点点之间的线的斜率必然是在单调递增的,于是

以上是关于最佳牛围栏的主要内容,如果未能解决你的问题,请参考以下文章

102. 最佳牛围栏(二分)

102. 最佳牛围栏

最佳牛围栏(前缀和+二分)

最佳牛围栏

102. 最佳牛围栏

102. 最佳牛围栏二分 / 思维 不错