洛谷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\n",ans); 61 return 0; 62 }
本文为博主原创文章,转载请注明出处。