zoukankan      html  css  js  c++  java
  • Best Cow Fences

    POJ

    题意:给定(N(N<=10^5))个正整数的数列,求一个平均数最大且长度不小于m的连续的子段.输出子段和乘上1000之后的整数即可.

    分析:实数域上的二分答案,每次直接二分平均数mid,然后令序列中的每个数减去该mid,对得到的新数列求前缀和sum,最后判定最大子段和是否非负即可.

    至于如何求出新数列的最大子段和?用一个变量(minn)记录最小的(sum[j]),每次i递增时,与(sum[i-m])(min)来更新(minn),然后用(sum[i]-minn)更新最大子段和(ans)即可.

    //#include<bits/stdc++.h>
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    using namespace std;
    inline int read() {
        int x=0,o=1;char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
        if(ch=='-')o=-1,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*o;
    }
    const int N=100005;
    int n,m,a[N];
    double b[N],sum[N];
    inline bool check(double mid){
    	for(int i=1;i<=n;++i)b[i]=a[i]*1.0-mid;
    	for(int i=1;i<=n;++i)sum[i]=sum[i-1]+b[i];
    	double ans=-1e9,minn=1e9;
    	for(int i=m;i<=n;++i){
    		minn=min(minn,sum[i-m]);
    		ans=max(ans,sum[i]-minn);
    	}
    	if(ans>=0)return true;
    	else return false;
    }
    int main(){
    	n=read(),m=read();
    	for(int i=1;i<=n;++i)a[i]=read();
    	double l=0.0,r=1e9,eps=1e-6;
    	while(r-l>eps){
    		double mid=(l+r)/2.0;
    		if(check(mid))l=mid;
    		else r=mid;
    	}
    	printf("%d
    ",(int)(r*1000));
        return 0;
    }
    
    
  • 相关阅读:
    IOS之UIAlert​Controller
    IOS实现弹出菜单效果MenuViewController(背景 景深 弹出菜单)
    IOS之正则表达式
    死锁与递归锁
    线程与进程的一些应用
    开启线程的两种方式
    互斥锁
    进程的队列
    模拟抢票系统
    Python并发编程__多进程
  • 原文地址:https://www.cnblogs.com/PPXppx/p/11228472.html
Copyright © 2011-2022 走看看