题目链接
https://ac.nowcoder.com/acm/contest/11255/J
题目大意
给定一个
n
∗
m
(
1
≤
n
,
m
≤
2
∗
1
0
5
)
n*m(1 \leq n,m \leq 2*10^5)
n∗m(1≤n,m≤2∗105)的矩阵W,矩阵上的元素满足
W
i
,
j
=
a
i
+
b
j
W_{i,j}=a_i+b_j
Wi,j=ai+bj,已知
a
i
,
b
j
(
1
≤
a
i
,
b
j
≤
1
0
5
)
a_i,b_j(1 \leq a_i,b_j \leq 10^5)
ai,bj(1≤ai,bj≤105)。
求其平均值最大的连续子矩阵,且满足第一维度至少为
x
(
1
≤
x
≤
n
)
x(1 \leq x \leq n)
x(1≤x≤n),第二维度至少为
y
(
1
≤
y
≤
m
)
y(1 \leq y \leq m)
y(1≤y≤m)。
题解
由构成方式易得,
W
i
,
j
W{i,j}
Wi,j的值是由
a
i
,
b
j
a_i,b_j
ai,bj决定的,且两个互不干涉,所以我们可以找a数组的连续最大平均值和b数组的连续最大平均值(至少大于等于x,y)。
由于最大值为
1
0
5
10^5
105我们想到,可以二分平均值的最大值,分别跑一次两个数组在相加就可以了。
参考代码
#include<bits/stdc++.h>
int n,m,x,y,a[100005],b[100005];
double tmp[100005],ans;
bool checka(double z){ //a数组条件
for(int i=1;i<=n;i++)tmp[i]=tmp[i-1]+a[i]-z;
double p=0x3f3f3f;
for(int i=x;i<=n;i++){
p=std::min(p,tmp[i-x]);
if(tmp[i]-p>=0)return true;
}
return false;
}
bool checkb(double z){ //b数组条件
for(int i=1;i<=m;i++)tmp[i]=tmp[i-1]+b[i]-z;
double p=0x3f3f3f;
for(int i=y;i<=m;i++){
p=std::min(p,tmp[i-y]);
if(tmp[i]-p>=0)return true;
}
return false;
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
std::cin>>n>>m>>x>>y;
for(int i=1;i<=n;i++)std::cin>>a[i];
for(int i=1;i<=m;i++)std::cin>>b[i];
int t=100;
double l=0,r=100000,mid;
while(t--){ //a数组二分
mid=(l+r)/2;
if(checka(mid))l=mid;
else r=mid;
}
ans=(l+r)/2;
t=100;
l=0,r=100000;
while(t--){ //b数组二分
mid=(l+r)/2;
if(checkb(mid))l=mid;
else r=mid;
}
printf("%.7lf\n",ans+(l+r)/2);
return 0;
}
针对一个给定的大规模矩阵,本文介绍了一种高效算法来找到满足特定尺寸约束的连续子矩阵,使其平均值最大。该算法利用了二分查找及前缀和技巧,分别在两个独立的一维数组上进行操作。
761

被折叠的 条评论
为什么被折叠?



