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)(二分图)