洛谷P1565 牛宫

题目描述

AP 神牛准备给自己盖一座很华丽的宫殿。于是,他看中了一块N*M 的矩形空地。

空地中每个格子都有自己的海拔高度。AP 想让他的宫殿的平均海拔在海平面之上(假设

海平面的高度是0,平均数都会算吧?)。而且,AP 希望他的宫殿尽量大,能够容纳更

多的人来膜拜他。请问AP 的宫殿最后会有多大?

输入输出格式

输入格式:

第一行为N 和M。之后N 行,每行M 个数,描述的空地的海拔。

输出格式:

输出一行,表示宫殿最大面积。

输入输出样例

输入样例#1:
3 2
4 0
-10 8
-2 -2
输出样例#1:
4

单调栈+dp

O(n^2)枚举矩形左右范围,从上往下扫每一行,如果从1到k行的总和大于0,那么整块矩形可选;如果总和小于零,将其存入一个单调递减的单调栈,这样在之后的计算中,如果smm(1~k) - smm(1~x)>0,那么行x+1到行k这部分矩形可选。查询时候用二分查找比较快。

万万没想到这题需要开long long,wa了一片

 1 /*by SilverN*/
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<cstring>
 5 #include<cstdio>
 6 #include<cmath>
 7 #include<vector>
 8 #define LL long long
 9 using namespace std;
10 const int mxn=310;
11 int read(){
12     int x=0,f=1;char ch=getchar();
13     while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();}
14     while(ch>='0' && ch<='9'){x=x*10+ch-'0';ch=getchar();}
15     return x*f;
16 }
17 int a[mxn][mxn];
18 LL smm[mxn][mxn];
19 int n,m;
20 int ans=0;
21 int f[mxn];
22 LL st[mxn];
23 int top=0;
24 int find(LL x){
25     int l=1,r=top,w=-1;
26     while(l<=r){
27         int mid=(l+r)>>1;
28         if(st[mid]<x)r=mid-1,w=mid;
29         else l=mid+1;
30     }
31     return w;
32 }
33 int main(){
34     n=read();m=read();
35     int i,j;
36     for(i=1;i<=n;i++)
37      for(j=1;j<=m;j++){
38          a[i][j]=read();
39          smm[i][j]=smm[i][j-1]+a[i][j];
40      }
41     st[0]=1e10;
42     for(i=1;i<=m;i++)//左边界 
43      for(j=i;j<=m;j++){//右边界
44          LL tmp=0;
45          top=0;
46          for(int k=1;k<=n;k++){
47             tmp+=smm[k][j]-smm[k][i-1];
48             if(tmp>0)ans=max(ans,(j-i+1)*k);
49             else{
50                 int pos=find(tmp);
51                 if(pos!=-1)
52                     ans=max(ans,(k-f[pos])*(j-i+1));
53             }
54             if(tmp<st[top]){
55                 st[++top]=tmp;
56                 f[top]=k;
57             }
58          }
59     }
60     printf("%d
",ans);
61     return 0;
62 }
原文地址:https://www.cnblogs.com/SilverNebula/p/6067295.html