[二分][前缀和] Jzoj P4809 挖金矿

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

题解

  • 发现直接做好像不可做,答案满足单调性
  • 考虑用二分将问题转换为判断性问题,设sum[i][]为第i列的前缀和
  • 设当前二分出答案为x,第i列往下挖h[i]层,那么就要满足
  • 移项就可以得出
  • 那么就枚举每行h[i],然后相加,看是否为正(注意精度问题)

代码

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <cstring>
 4 #define ll long long 
 5 using namespace std;
 6 const ll N=1e5+10;
 7 ll n,h,a[N],sum[N];
 8 double l,r,s,mx,mid;
 9 int main()
10 {
11     scanf("%lld%lld",&n,&h);
12     for (ll i=1;i<=n;i++)
13         for (ll j=1;j<=h;j++)
14         {
15             scanf("%lld",&a[(i-1)*h+j]);
16             if (a[(i-1)*h+j]>r)r=a[(i-1)*h+j];
17             if (j!=1) sum[(i-1)*h+j]=sum[(i-1)*h+j-1]+a[(i-1)*h+j]; else sum[(i-1)*h+j]=a[(i-1)*h+j];
18         }
19     while (l+0.000001<r)
20     {
21         mid=(l+r)/2.0,s=0;
22         for (ll i=1;i<=n;i++)
23         {
24             mx=-2147483647;
25             for (ll j=1;j<=h;j++) mx=max(mx,sum[(i-1)*h+j]-j*mid);
26             s+=mx;
27         }
28         if (s>=0) l=mid; else r=mid;
29     }
30     printf("%.4lf",mid);
31 }

猜你喜欢

转载自www.cnblogs.com/Comfortable/p/11127128.html
今日推荐