POJ2018 Best Cow Fences (二分答案+類前綴和)


題意

Farmer John's farm consists of a long row of N (1 <= N <= 100,000)fields. Each field contains a certain number of cows, 1 <= ncows <= 2000.

FJ wants to build a fence around a contiguous group of these fields in order to maximize the average number of cows per field within that block. The block must contain at least F (1 <= F <= N) fields, where F given as input.

Calculate the fence placement that maximizes the average, given the constraint.

大意是說,給你一個正整數序列,找出一個區間使得平均值最大,要求該區間的長度大於等於F。

方法

做法來源於先輩,再在此特別感謝
據說有類似凸包優化,學會后再寫一遍吧

注意到(1 <= N <= 100,000),因此傳統方法(暴力)就算上了前綴和,時間復雜度也是平方級別的,必然超時。

方法是:先二分答案。接着對於每個候選答案,盡量在O(n)時間內驗證。

那么怎么盡快驗證答案呢?

想象一個情景:一個固定左端起點長度為F的區間向右生長,直至平均值對大。循環n次來更換不同起點,所有情況都能考慮周全。

這里需要優化。首先,知道平均值要知道總和,長度為F時的和可以用前綴和一步得到。

向右延長這步也可以類似去做。我們要首先把所有整數都減去當前的候選答案。這一步很關鍵,因為我們要獲取的是 平均值的最大,減去后,我們便可以直接使用確定起點向右的數字的和作為狀態,而不用再考慮除掉個數來計算對平均值的影響。

定義t[i]為以i為起點,向右延長的最大和。如果t[i+1]>=0,那么t[i]=t[i+1]+w[i]。若t[i+1]<0,那么不如扔掉i+1及其之后的數字,故此時t[i]=w[i]。

這樣,能保證O(n)時間內驗證候選答案。

代碼

#include<iostream>
#include<cstdio>
#include<string.h>
using namespace std;
const int MAXN=100000+5;
int N,F;
double num[MAXN];
double sum[MAXN];
double rmaxsum[MAXN];
double l=9999999,r;
inline bool qualify(double tans){
    for(int i=N;i>=1;i--)
        rmaxsum[i]=max(num[i]-tans,rmaxsum[i+1]+num[i]-tans);
    for(int i=1;i<=N-F+1;i++){
    //  cout<<sum[i+F-1]-sum[i-1]<<" "<<F*tans<<" "<<tans<<endl;
        if(sum[i+F-1]-sum[i-1]>=F*tans)
            return true;
    //  cout<<"sec:"<<sum[i+F-1]-sum[i-1]-F*tans+rmaxsum[i+F]<<endl;
        if(sum[i+F-1]-sum[i-1]-F*tans+rmaxsum[i+F]>=0)
            return true;
    }
    return false;
}
int main(){
    cin>>N>>F;
    for(int i=1;i<=N;i++){
        scanf("%lf",&num[i]);
        sum[i]=sum[i-1]+num[i]; 
        r=max(r,num[i]);
        l=min(l,num[i]);
    }
    while(l<r-0.0001){
        double mid=(r+l)/2;
        if(qualify(mid))
            l=mid;
        else
            r=mid;
    }
    cout<<int(r*1000)<<endl;
    return 0;
} 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM