码迷,mamicode.com
首页 > 其他好文 > 详细

最佳牛围栏

时间:2019-07-18 16:40:53      阅读:174      评论:0      收藏:0      [点我收藏+]

标签:pre   define   int   free   最小   ffffff   gis   ima   while   

最佳牛围栏

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

[警告:此题卡精度]

法一:二分

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

\[\frac{\sum_{i=l}^ra_i}{r-l+1}=\bar{x}\]

经过式子变换有其二分式

\[\sum_{i=l}^r(a_i-\bar{x})=0\]

于是只要判断左式答案与0的关系,就可以确定是否有最优解了,当左式的最大值大于0时,我们就可以知道\(\bar{x}\)可以更加优秀,反之,于是问题变成如何求左式的最大值,不妨构造新数列\(\{b_i\}\),有\(b_i=a_i-\bar{x}\),现在问题转化为求数列\(\{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}\{\frac{s_i-s_j}{i-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点,而根据凸壳的规律后面的点点之间的线的斜率必然是在单调递增的,于是

最佳牛围栏

标签:pre   define   int   free   最小   ffffff   gis   ima   while   

原文地址:https://www.cnblogs.com/a1b3c7d9/p/11208082.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!