Description
Input
Output
Sample Input
4 3
4 3 3
5 1 6
2 6 1
3 2 9
Sample Output
4.4286
Data Constraint
Hint
Source / Author: 学军中学 gold
题解:
二分。
二分期望平均数mid,如果这个mid是可能的,则
化简得 sum(a[i] - mid)>=0
所以,对于任意一个mid,只需要把所有矿的价值减去mid,然后每一列做一个前缀和。
对于每一列的前缀和数组,取出一个最大值加到sum中(sum初始值为0),最后看sum是否大于等于0即可。
#include<bits/stdc++.h>
#define N 100010
#define inf 2147483647
#define open(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout)
#define mem(a,b) memset(a,b,sizeof(a))
#define mcy(a,b) memcpy(a,b,sizeof(a))
using namespace std;
struct point
{
double next,val,pre;
}a[N];
int i,j,tot,n,h;
double maxx,root[N];
double l,r,mid,ans;
void make()
{
for(i=1;i<=n;i++)
{
int p=root[i],last=0;
while(p)
{
a[p].pre = a[p].val - mid + a[last].pre;
last=p;
p=a[p].next;
}
}
}
double gain()
{
double sum=0;
for(i=1;i<=n;i++)
{
int p=root[i],last=0;
double tmp=-inf;
while(p)
{
tmp = max(tmp,a[p].pre);
p=a[p].next;
}
sum+=tmp;
}
return sum;
}
int main()
{
open("goldmine");
scanf("%d%d",&n,&h);
for(i=1;i<=n;i++)
{
for(j=1;j<=h;j++)
{
++tot;
scanf("%lf",&a[tot].val); maxx = max(maxx,a[tot].val);
if(j!=1) a[tot-1] . next = tot; else root[i] = tot;
}
}
l=1.00;
r=maxx;
while((r-l)>0.00001)
{
mid = (l+r) / 2.00;
make();
if(gain() >=0.00)
{
ans = mid;
l = mid;
} else r = mid;
}
printf("%.4lf",ans);
return 0;
}
O(n log n)