2021牛客多校第四场 补题

J-Average

链接:https://ac.nowcoder.com/acm/contest/11255/J
来源:牛客网
 

Bob has an n×mn\times mn×m matrix WWW. 

This matrix is very special, It's calculated by two sequences a1...n,b1...ma_{1...n},b_{1...m}a1...n​,b1...m​, ∀i∈[1,n],∀j∈[1,m]\forall i\in [1,n],\forall j\in [1,m]∀i∈[1,n],∀j∈[1,m], Wi,j=ai+bjW_{i,j}=a_{i}+b_{j}Wi,j​=ai​+bj​

Now Bob wants to find a submatrix of WWW with the largest average value.

Bob doesn't want the size of submatrix to be too small, so the submatrix you find must satisfy that the width(the first dimension of matrix) of it is at least xxx and the height(the second dimension of matrix) of it is at least yyy.

Now you need to calculate the largest average value.

输入描述:

The first line has four integers n,m,x,yn,m,x,yn,m,x,y.

The second line has nnn integers a1...na_{1...n}a1...n​.

The third line has mmm integers b1...mb_{1...m}b1...m​.

1≤n,m≤1051\leq n,m\leq 10^51≤n,m≤105

1≤x≤n,1≤y≤m1\leq x\leq n,1\leq y\leq m1≤x≤n,1≤y≤m

0≤ai,bi≤1050\leq a_i,b_i\leq 10^50≤ai​,bi​≤105

输出描述:

Output the largest average value.

Your answer will be considered correct if the absolute or relative error is less than 10−610^{-6}10−6

题目大意

 每一个单位的值Ci,j =ni+mj  选择一个矩形 使其中的平均ci,j最大,其中保证选中矩形的大小不能小于x行y列

思路

其实题目就转变为对于ni 和mi两个数组 在区间大于给定限制的情况下选择最大的平均值

利用二分去计算 这个平均值

l=min ai ,r=max ai  (a数组即m或n数组)

check函数是将所有ai减去mid 然后 遍历1-n 不断记录新的前缀和sum [i]

同时记录最小前缀和 sum[i-k] 令prev =min(pre,sum[i-k])

当sum[i]-prev>0 return 1;

ps:对于eps的选择没必要那么精细 输出只需要输出.6lf就足够了 比赛时样例误导了我

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int maxn=1e5+10;
int a[maxn],b[maxn],suma[maxn],sumb[maxn];
int n,m,x,y;
int pa,pb;
int amax,bmax,amin,bmin;
bool check( double mid,int k) {
        double sum = 0, prev = 0, min_sum = 0;
        for (int i = 0; i < k; i++)
            sum += a[i] - mid;
        if (sum >= 0)
            return true;
        for (int i = k; i < n; i++)
		 {
            sum += a[i] - mid;
            prev += a[i - k] - mid;
            min_sum = min(prev, min_sum);
            if (sum >= min_sum)
                return true;
        }
        return false;
}
bool check1( double mid,int k) {
        double sum = 0, prev = 0, min_sum = 0;
        for (int i = 0; i < k; i++)
            sum += b[i] - mid;
        if (sum >= 0)
            return true;
        for (int i = k; i < m; i++)
		 {
            sum += b[i] - mid;
            prev += b[i - k] - mid;
            min_sum = min(prev, min_sum);
            if (sum >= min_sum)
                return true;
        }
        return false;
}


int main()
{
	cin>>n>>m>>x>>y;
	amin=inf;
	bmin=inf;
	for(int i=0;i<n;i++)
	{
		cin>>a[i];
		suma[i]=suma[i-1]+a[i];
		amax=max(amax,a[i]);
		amin=min(amin,a[i]);
	}
	for(int i=0;i<m;i++)
	{
		cin>>b[i];
		sumb[i]=sumb[i-1]+b[i];
		bmax=max(bmax,b[i]);
		bmin=min(bmin,b[i]);
	}
	//cout<<amin<<amax<<endl;
	double ans=0;
	double l=(double)amin;
	double r=(double)amax;
	while(r-l>0.00000001)
	{
		//cout<<l<<endl;
		double mid=(l+r)/2.0;
		//cout<<mid<<endl;
		if(check(mid,x))
		{
			l=mid;
		}
		else r=mid;
		
	}
	ans+=l;
	//cout<<ans<<endl;
	l=(double)bmin;
	 r=(double)bmax;
	while(r-l>0.00000001)
	{
		double mid=(l+r)/2.0;
		if(check1(mid,y))
		{
			l=mid;
		}
		else r=mid;
		
	}
	ans+=l;
	printf("%.7lf\n",ans); 
	return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值