• AcWing102 最佳牛围栏 (二分)


    题目链接:https://www.acwing.com/problem/content/104/

    先考虑一个经典问题,求最大连续子段和,无长度限制:
    扫描序列,不断将新的数加入子段,当子段和为负数时,清空当前子段

    若有长度限制:
    维护前缀和(sum),减去(i-L)之前的前缀和的最小值

    对于这道题,二分平均值,将序列减去(mid),判断最大子段和能否大于(0)

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #include<cmath>
    #include<stack>
    #include<queue>
    using namespace std;
    typedef long long LL;
    
    const int MAXN = 100010;
    const double INF = 1000000007;
    const double eps = 1e-5;
    
    int N,L;
    double a[MAXN], b[MAXN], sum[MAXN];
    
    bool check(double x){
    	for(int i=1;i<=N;++i) b[i] = a[i] - x;
    	for(int i=1;i<=N;++i) sum[i] = (sum[i-1] + b[i]);
    	
    	double min_val = INF, ans = -INF;
    	
    	for(int i=L;i<=N;++i){
    		min_val = min(min_val, sum[i-L]);
    		ans = max(ans, sum[i] - min_val);
    	}
    	if(ans >= 0) return true; else return false;
    }
    
    LL read(){ LL s=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9'){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0' && ch<='9'){ s=s*10+ch-'0'; ch=getchar(); } return s*f; }
    
    int main(){
    	N = read(), L = read();
    	for(int i=1;i<=N;++i) scanf("%lf",&a[i]);
    	
    	double l = 0, r = 2000.0;
    	
    	while(r - l > eps){
    		double mid = (l + r) / 2;
    		if(check(mid)) l = mid;
    		else r = mid;
    	}
    	
    	printf("%d
    ",(int)(r*1000));
    	
    	return 0;
    }
    
  • 相关阅读:
    Groovy Urlencode编码
    PowerShell导入自定义公共函数
    Groovy获取对象类型、属性
    adb名称操作模拟器
    《坚不可摧》——乔布斯演讲
    马拉松节奏跑(转载)
    马拉松配速
    什么是思考力三要素?(转载)
    Python解析JSON为实体
    excel宏的用法
  • 原文地址:https://www.cnblogs.com/tuchen/p/13910948.html
Copyright © 2020-2023  润新知