题目描述
AP 神牛准备给自己盖一座很华丽的宫殿。于是,他看中了一块N∗M 的矩形空地。空地中每个格子都有自己的海拔高度。AP 想让他的宫殿的平均海拔在海平面之上(假设海平面的高度是0 ,平均数都会算吧?)。而且,
输入
第一行为N 和
输出
输出一行,表示宫殿最大面积。
样例输入
3
4
−10 8
样例输出
4
提示
对于
对于100% 的数据,N,M≤200
解法
(首先,宫殿也是矩形= =)
这题n 6 和n 4 暴力很显然
在n 4 的思路上进行优化。保留枚举子矩阵的左右端的列,在行的枚举上做优化。对于一个确定的L、R ,可以用行前缀和O(1) 知道第i 行在这个区间内的值
我们要找一个平均值大于0 的区间,就是需要找到一段和大于
对s[i][R]−s[i][L−1] 做前缀和,即S[k]=∑ k i=1 (s[i][R]−s[i][L−1])
问题现在就转化成为找一个i∈[0,k) 使得S[k]−S[i]>0 且i尽量小。
因为我们现在求一个区间的值可以用S 数组相减得到结果,所以注意到一个性质,如果对于一个数
所有比
于是乎……选择性地保留一些
(这是一个单调栈)
然后更新答案时二分查找单调栈中第一个可行元素。
时间代价n 3 log(n)
(题外话一:我还写了个n 3 log(lim) 的线段树硬上失败……)
(题外话二:数据有点水,暴力优化一下就跑过了……)
代码
#include<stdio.h>
#define ll long long
#define N 250
#define lim 1000000000000
int n,m,ans,l,r,mid,q[N];
long long s[N][N],S[N];
inline int max(const int &a,const int &b){return (a<b)?b:a;}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1,a;i<=n;i++) for (int j=1;j<=m;j++) scanf("%d",&a),s[i][j]=s[i][j-1]+a;
for (int i=1;i<=m;i++) for (int j=i,t=0;j<=m;j++,t=0) for (int k=1;k<=n;k++)
{
if ((S[k]=S[k-1]+s[k][j]-s[k][i-1])<S[q[t]]) q[++t]=k;
for (l=0,r=t,mid=(l+r)>>1;l<r;mid=(l+r)>>1) if (S[q[mid]]<S[k]) r=mid;
else l=mid+1;
ans=max(ans,(k-q[l])*(j-i+1));
}
printf("%d\n",ans);
}
本文介绍了一个关于寻找最大面积的矩形区域,其平均海拔高于海平面的问题。通过优化行枚举,利用行前缀和及单调栈技巧,实现了n³log(n)的时间复杂度。
582

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



