Description
AP 神牛准备给自己盖一座很华丽的宫殿。于是,他看中了一块 N*M 的矩形空地。空地
中每个格子都有自己的海拔高度。AP 想让他的宫殿的平均海拔在海平面或海平面之上(假
设海平面的高度是 0,平均数都会算吧?) 。而且,AP 希望他的宫殿尽量大,能够容纳更多
的人来膜拜他。请问 AP 的宫殿最后会有多大?
Input Format
第一行为 N 和 M。之后 N 行,每行 M 个数,描述的空地的海拔。
Output Format
输出一行,表示宫殿最大面积。
Sample Input
3 2
4 0
-10 8
-2 -2
Sample Output
4
Data Limit
对于 30%的数据,N,M≤50;
对于 100%的数据,N,M≤200;
根据数据范围可知复杂度O(n^3(logn))
然后我们求出矩形的二维前缀和s
对于矩形(i,x)~(j,y)
和为(s[i][y]-s[j-1][y])-(s[i][x]-s[j-1][x])
令d=s[i][y]-s[j-1][y]
也就是找到一个s[i][x]-s[j-1][x]小于当前的d
我们在枚举了行的上下界,再枚举一个列的右界
接下来在右界向右移时,更新单调递减的栈,如果小于栈顶,则加入
那么就可以二分查找一个最靠前的不大于d的值
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 using namespace std; 7 long long a[201][201],n,m,f[2001],s[201][201]; 8 long long ans; 9 int main() 10 { 11 long long i,j,k; 12 cin>>n>>m; 13 for(i=1; i<=n; i++) 14 for(j=1; j<=m; j++) 15 scanf("%lld",&a[i][j]),a[i][j]+=a[i][j-1],s[i][j]=s[i-1][j]+a[i][j]; 16 for (i=1; i<=n; i++) 17 { 18 for (j=1; j<=i; j++) 19 { 20 int top=1; 21 f[1]=0; 22 for (k=1; k<=m; k++) 23 { 24 int l=1,r=top,cnt=k; 25 while (l<=r) 26 { 27 int mid=(l+r)/2; 28 if ((s[i][k]-s[j-1][k])-(s[i][f[mid]]-s[j-1][f[mid]])>=0) cnt=f[mid],r=mid-1; 29 else l=mid+1; 30 } 31 ans=max(ans,(i-j+1)*(k-cnt)); 32 if (s[i][k]-s[j-1][k]<s[i][f[top]]-s[j-1][f[top]]) f[++top]=k; 33 } 34 } 35 } 36 cout<<ans; 37 }