【NOIP2016提高A组五校联考1】挖金矿

题目

这里写图片描述

分析

我们二分答案
(sum_{i,j})表示的i列前个数的和,
假设当前出的二分答案为x,第i列挖了(h_j)层,则

[dfrac{sum_{i=1}^{n}sum_{i,h_i}}{sum_{i=1}^{n}h_i}>=x ]

转移得(sum_{i=1}^{n}sum_{i,h_i}-sum_{i=1}^{n}h_ix>=0)
那么对于每一列,把最大的(sum_{i,h}-hx)求出了,加在一起就可以了。

#include <cmath>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
const long long maxlongint=214748364700000;
const int mo=1000000007;
const int N=50005;
using namespace std;
int n,m,p,g,a[N*2];
long long sum[N*2];
int rf(double l,double r)
{
	while(l+0.000001<r)
	{
		double mid=(l+r)/2,num=0,p;
		for(int i=1;i<=n;i++)
		{
			p=-maxlongint;
			for(int j=1;j<=m;j++)
			{
				if(sum[(i-1)*m+j]-j*mid>p)
				{
					p=sum[(i-1)*m+j]-j*mid;
				}
			}
			num+=p;
		}
		if(num<0)
			r=mid;
		else
			l=mid;
	}
	printf("%.4lf",l);
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			scanf("%d",&a[(i-1)*m+j]);
			if(j==1)
				sum[(i-1)*m+j]=a[(i-1)*m+j];
			else
				sum[(i-1)*m+j]=sum[(i-1)*m+j-1]+a[(i-1)*m+j];
		}
	}
	rf(1,maxlongint);
}

原文地址:https://www.cnblogs.com/chen1352/p/9051706.html