2021牛客暑期多校训练营4Average (二分答案,区间/子数组最大平均值,)

Posted 小哈里

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2021牛客暑期多校训练营4Average (二分答案,区间/子数组最大平均值,)相关的知识,希望对你有一定的参考价值。

J Average

题意:

  • 给出长为n,m的序列ai和bi,定义nm的矩阵wij=ai+bj,求一个大小>=xy的子矩阵的平均值最大。

思路:

  • 因为n的范围为1e5,直接n*m计算出wij就已经超时,所以考虑贡献。从wij的矩阵平均值公式可以推出平均值分别为a和b的最大平均值相加。
  • 所以答案就是分别对 a 和 b 对应的区间求平均值然后加起来,问题转化成了 : 找 a 的一个长度至少为 x 的平均值最大的子区间和 b 的一个长度至少为 y 的平均值最大的子区间
  • 二分答案 S 后, 令 a[i] 变成 a[i]-S, 则问题变成求是否有和 >0 的长度至少为 x 的子区间, 这个可以 O(n) 计算 时间复杂度 O(nlogW)
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn = 4e5+10;
const double esp = 1e-10;

double a[maxn], b[maxn], tmp[maxn];
bool check(double num[], double avg, int n, int k){
	for(int i = 1; i <= n; i++)tmp[i]=num[i]-avg;
	for(int i = 1; i <= n; i++)tmp[i]+=tmp[i-1];
	double mi = 1e5+10;
	for(int i=k; i <= n; i++){
		mi = min(mi,tmp[i-k]);
		if(tmp[i]-mi>=0)return true;
	}
	return false;
}
double solve(double num[], int n, int k){
	double l = -1e5, r = 1e5;
	while(l+esp <= r){
		double mid = (l+r)/2.0;
		if(check(num, mid, n, k))l = mid;
		else r = mid;
	}
	return l;
}

int main(){
	int n, m, x, y;  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("%.7lf", solve(a,n,x)+solve(b,m,y));
	return 0;
}

以上是关于2021牛客暑期多校训练营4Average (二分答案,区间/子数组最大平均值,)的主要内容,如果未能解决你的问题,请参考以下文章

2021牛客暑期多校训练营10 War of Inazuma (Easy Version)(二分图)

2021牛客暑期多校训练营3 C.Minimum grid 二分图最大匹配

2021牛客暑期多校训练营9 E.Eyjafjalla

2021牛客暑期多校训练营9 E.Eyjafjalla

2021牛客暑期多校训练营9 E.Eyjafjalla

2021牛客暑期多校训练营9 E.Eyjafjalla