歌名 - 歌手
0:00

    【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);
    }
    
    
    posted @ 2018-05-17 16:15  无尽的蓝黄  阅读(164)  评论(0编辑  收藏  举报