牛宫

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 }

 

posted @ 2017-10-31 14:54  Z-Y-Y-S  阅读(405)  评论(0编辑  收藏  举报