POJ 2018 Best Cow Fences 斜率优化/二分

Best Cow Fences POJ - 2018

N(1N100,000)N(1\le N\le 100,000) 块地,每块地有 n(1n2000)n(1\le n\le2000) 头牛。

在这些地之间建两个篱笆,这两个篱笆中间包含的是连续的地,使得该篱笆内平均每块地的牛数最多,每两个篱笆中间至少有 F(1FN)F(1\le F\le N) 块地。

这个题跟 HDU 2993 MAX Average Problem 斜率DP+IO优化 是一样的。

维护一个斜率单增的单调队列,找 ii 的斜率最大对应点时从队列的开头进行判断。

代码如下(时间复杂度 O(n)O(n)):

#include<iostream>
#include<cstdio>
#include<algorithm>
//#define WINE
#define MAXN 100100
using namespace std;
int n,f,a[MAXN],s[MAXN],h,t,q[MAXN],res;
int up(int j,int k){
    return s[j]-s[k];
}
int down(int j,int k){
    return j-k;
}
int main(){
#ifdef WINE
    freopen("data.in","r",stdin);
#endif
    scanf("%d%d",&n,&f);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]),s[i]=s[i-1]+a[i];
    h=t=0;q[t++]=0;
    for(int i=f;i<=n;i++){
        while(h+1<t&&up(i,q[h])*down(i,q[h+1])<up(i,q[h+1])*down(i,q[h]))
            h++;
        res=max(res,(s[i]-s[q[h]])*1000/(i-q[h]));
        int j=i-f+1;
        while(h+1<t&&up(j,q[t-1])*down(q[t-1],q[t-2])<up(q[t-1],q[t-2])*down(j,q[t-1]))
            t--;
        q[t++]=j;
    }
    printf("%d\n",res);
    return 0;
}

在这里插入图片描述
还可以用二分写:

#include<iostream>
#include<cstdio>
#include<algorithm>
//#define WINE
#define INF 0x3f3f3f3f
#define MAXN 100010
using namespace std;
int n,f,a[MAXN],Min=INF,Max=0;
double s[MAXN],l,r,mid,cur;
bool check(double k){
    for(int i=1;i<=n;i++)s[i]=s[i-1]+a[i]-k;
    double m=0;
    for(int i=f;i<=n;i++){
        cur=s[i]-m;
        if(cur>=0)return true;
        m=min(m,s[i-f+1]);
    }
    return false;
}
int main(){
#ifdef WINE
    freopen("data.in","r",stdin);
#endif
    scanf("%d%d",&n,&f);
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        Min=min(Min,a[i]);
        Max=max(Max,a[i]);
    }
    l=Min;r=Max;
    double eps=1e-5;
    while(l+eps<r){
        mid=(l+r)/2;
        if(check(mid))l=mid;
        else r=mid;
    }
    printf("%d\n",(int)(r*1000));
    return 0;
}

在这里插入图片描述

posted @ 2020-03-24 09:35  winechord  阅读(107)  评论(0编辑  收藏  举报