最佳牛圍欄

AcWing 102. 最佳牛圍欄

比較有意思的一道題
總的思路就是二分+前綴和,不難,可是其中有的思想仍是有價值的
因此我就主要從這道題入手來淺談二分中的轉化斷定問題spa

思路

如何求一個字段,使和最大且自段長度不超過L

咕咕咕,寫不出數學公式來就只貼代碼吧code

double min_ans=0x3f3f3f,max_ans=-0x3f3f3f;
    for(int i=p; i<=n; ++i) {
        min_ans=min(min_ans,num[i-p]);
        max_ans=max(max_ans,num[i]-min_ans);
    }

核心思路

二分答案轉化爲斷定問題
這是一個頗有用的思路,藉助二分咱們能夠吧求最優解的問題轉化爲給定一個\(mid\)
,斷定是否存在一個可行方案評分達到\(mid\)的問題ci

之後會更新的數學

代碼

#include<bits/stdc++.h>
using namespace std;
const double eps=1e-6;
const int N=100001;
double a[N],num[N],l,r,b[N];
int n,p;
double max(double x,double y) {
    return x>=y?x:y;
}
double min(double x,double y) {
    return x<=y?x:y;
}
int check(double mid) {
    for(int i=1; i<=n; ++i)
        num[i]=a[i]-mid,num[i]+=num[i-1];   //處理前綴和
    double min_ans=0x3f3f3f,max_ans=-0x3f3f3f;
    for(int i=p; i<=n; ++i) {
        min_ans=min(min_ans,num[i-p]);
        max_ans=max(max_ans,num[i]-min_ans);
    }
    if(max_ans<=0) return 0;
    else return 1;
}
int main() {
    cin>>n>>p;
    for(int i=1; i<=n; ++i) cin>>a[i];
    l=0,r=1000000;
    while(r-l>eps) {
        double mid=(l+r)/2;
        if(check(mid)) l=mid;
        else r=mid;
    }
    cout<<int(r*1000);
    return 0;
}
相關文章
相關標籤/搜索