zoukankan      html  css  js  c++  java
  • 【JZOJ4256】平均数【二分】

    题目大意:

    题目链接:https://jzoj.net/senior/#main/show/4256
    给出包含一个NN个整数的数组AA。找出一段长度至少为mm的连续序列,最大化它的平均值。


    思路:

    很明显这道题的答案满足单调性。若可以找出一段区间的平均值超过kk,那么必然可以找到一段区间的平均值超过k1k-1
    那么可以考虑二分答案。
    设二分的答案为ansans

    (ija[i])÷(ji)ans(ji+1m)(sum^{j}_{i}a[i])div (j-i)geq ans(j-i+1geq m)

    ija[i]ans×(ji)sum^{j}_{i}a[i]geq ans imes (j-i)
    ija[i]ans×(ji)0sum^{j}_{i}a[i]-ans imes (j-i)geq 0
    ij(a[i]ans)0sum^{j}_{i}(a[i]-ans)geq 0
    于是可以用前缀和
    sum[i]=j=1i(a[i]ans)sum[i]=sum^{i}_{j=1}(a[i]-ans)
    然后我们就要最大化sum[i]sum[j](ij+1m)sum[i]-sum[j](i-j+1geq m)
    于是可以记录max(sum[k])(k1j1)max(sum[k])(kin 1sim j-1)。然后枚举ii,判断最大化后可否超过0。
    时间复杂度O(n log n)O(n log n)


    代码:

    #include <cstdio>
    #include <iostream>
    using namespace std;
    
    const int N=300010;
    int n,m;
    double l,r,mid,a[N],sum[N];
    
    bool check(double ans)
    {
    	sum[0]=0;
    	for (int i=1;i<=n;i++)
    		sum[i]=sum[i-1]+a[i]-mid;
    	double minn=0;
    	for (int i=m;i<=n;i++)
    	{
    		minn=min(minn,sum[i-m]);  //记录最小值
    		if (sum[i]>=minn) return 1;  //含有一个长度超过m的区间平均值超过0
    	}
    	return 0;
    }
    
    int main()
    {
    	freopen("average.in","r",stdin);
    	freopen("average.out","w",stdout);
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=n;i++)
    		scanf("%lf",&a[i]);
    	l=0;
    	r=1000000;
    	while (r-l>=0.0001)
    	{
    		mid=(l+r)/2.0;
    		if (check(mid)) l=mid;
    			else r=mid;
    	}
    	printf("%lf",l);
    	return 0;
    }
    
  • 相关阅读:
    Opencv(1)介绍篇
    植被覆盖度制图
    GIS应用开发AO(2)-空间分析ITopologicalOperate
    GIS应用开发AO(1)_普通几何图形绘制
    初识机器学习-人脸识别
    ArcGIS API for javascript4.3——RouteTask
    javascript学习(1)随机点名应用
    生活感悟之六
    生活感悟之五
    生活感悟之四
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998321.html
Copyright © 2011-2022 走看看