题目描述
AP 神牛准备给自己盖一座很华丽的宫殿。于是,他看中了一块N*M 的矩形空地。
空地中每个格子都有自己的海拔高度。AP 想让他的宫殿的平均海拔在海平面之上(假设
海平面的高度是0,平均数都会算吧?)。而且,AP 希望他的宫殿尽量大,能够容纳更
多的人来膜拜他。请问AP 的宫殿最后会有多大?
输入输出格式
输入格式:
第一行为N 和M。之后N 行,每行M 个数,描述的空地的海拔。
输出格式:
输出一行,表示宫殿最大面积。
输入输出样例
输入样例#1:
3 2 4 0 -10 8 -2 -2
输出样例#1:
4
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
单调栈+动态规划+前缀和+二分~
(所以为什么是普及+/提高啊!)
我们枚举长方形的宽的左右坐标,然后对于每个位置,求出它的最长长,乘起来更新面积。
用前缀和数组记录一下,可以很方便地计算。
正解:
#include<cstdio>
#include<iostream>
using namespace std;
#define ll long long
ll n,m,x,a[201][201],f[201],sta[201],len,ans;
ll findd(ll u)
{
ll l=1,r=len,tot=-1;
while(l<=r)
{
ll mid=(l+r)>>1;
if(sta[mid]<u)
{
r=mid-1;tot=mid;
}
else l=mid+1;
}
return tot;
}
int main()
{
scanf("%lld%lld",&n,&m);
for(ll i=1;i<=n;i++)
for(ll j=1;j<=m;j++)
{
scanf("%lld",&x);
a[i][j]=a[i][j-1]+x;
}
for(ll i=1;i<=m;i++)
for(ll j=1;j<=m;j++)
{
ll area=0;sta[0]=1e10;len=0;
for(ll k=1;k<=n;k++)
{
area+=a[k][j]-a[k][i-1];
if(area>0) ans=max(ans,k*(j-i+1));
else
{
int z=findd(area);
if(z!=-1) ans=max(ans,(j-i+1)*(k-f[z]));
}
if(sta[len]>area) sta[++len]=area,f[len]=k;
}
}
printf("%lld\n",ans);
return 0;
}
暴力四重循环,50分:
#include<cstdio>
#include<iostream>
using namespace std;
#define ll long long
ll n,m,k,a[1001][1001],now,ans,kkz;
int main()
{
scanf("%lld%lld",&n,&m);
for(ll i=1;i<=n;i++)
for(ll j=1;j<=m;j++)
{
scanf("%lld",&k);
a[i][j]=a[i-1][j]+a[i][j-1]-a[i-1][j-1]+k;
}
for(ll i1=1;i1<=n;i1++)
for(ll i2=i1;i2<=n;i2++)
{
if(ans) kkz=ans/(i2-i1+1)-1;
kkz=kkz<0 ? 0:kkz;
for(ll j1=1;j1<=m;j1++)
for(ll j2=j1+kkz;j2<=m;j2++)
{
now=a[i2][j2]+a[i1-1][j1-1]-a[i1-1][j2]-a[i2][j1-1];
if(now>=0) ans=max(ans,(i2-i1+1)*(j2-j1+1));
}
}
printf("%lld\n",ans);
return 0;
}