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;
    }
    
  • 相关阅读:
    京东分页
    相册分类列表页
    在线运行Javascript,Jquery,HTML,CSS代码
    点击事件后动画提示
    一些广告代码
    爱可有—之最经典
    爱可有网络社区需要定义
    鼠标移动时缩小图片显示说明
    Flask-RESTful 快速入门
    Sequelize 关系模型简介
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998320.html
Copyright © 2011-2022 走看看