题面:已知a[],b[],矩阵w[i][j]=a[i]+b[j],求矩阵的最大平均数,并且长不小于x,宽不小于y。
解析:易得average=
两者互不干扰,分别求二者的最大值即可。穷举会T,这道题可以用二分。
二分check函数写法:
我们要找的是 有没有一段不小于x的区间,使这段区间的平均数尽可能的大,如果我们找到了一段连续的区间且区间长度不小于x且平均数大于我们二分的平均数 那么大于这个数且区间也满足的一定满足了 我们直接判断正确即可
对于一段区间,每个数减去我们所算的平均数,如果大于0 那么他本身就大于平均数,如果小于0 那么它本身就小于平均数 此时我们就能算出哪些数大于0 哪些数小于0 ,之后我们再使用前缀和,就能判断一个区间内的平均值是否大于或小于我们二分的平均数了
对于满足区间长度不小于x,我们这里可以使用双指针的做法,我们设i=x,j=0, 每次使两个数++ 因此i,j始终满足相距FF的距离,所以我们用一个变量mi来存储所遍历到的最小值,这样我们比较的距离一定是≥F的,并且如果我们用前i位的前缀和减mi的话,就能得到我们的最优解,如果这个最优解> 0 那么就满足我们的指定条件
最佳牛围栏 借鉴大佬的思路!!!
代码:
#include<bits/stdc++.h> using namespace std; int n,m,x,y; double a[100005],b[100005]; double v[100005]; int check(double mid,double *a,int x,int n){ for(int i=1;i<=n;i++) v[i]=a[i]+v[i-1]-mid; double mi=v[0]; for(int i=x,j=0;i<=n;i++,j++){ mi=min(mi,v[j]); if(v[i]-mi>0) return 1; } return 0; } double fen(double *a,int x,int n){ double l=0,r=1e5; for(int i=0;i<=1000;i++){ double mid=(l+r)/2; if(check(mid,a,x,n)) l=mid; else r=mid; } return (r+l)/2; } int main(){ cin>>n>>m>>x>>y; for(int i=1;i<=n;i++) cin>>a[i]; for(int i=1;i<=m;i++) cin>>b[i]; printf("%.10lf\n",fen(a,x,n)+fen(b,y,m)); }