.牛宫
(long.pas/c/cpp)
【问题描述】
AP 神牛准备给自己盖一座很华丽的宫殿。于是,他看中了一块 N*M 的矩形空地。空
地中每个格子都有自己的海拔高度。AP 想让他的宫殿的平均海拔在海平面之上(假设海平
面的高度是 0,平均数都会算吧?) 。而且,AP 希望他的宫殿尽量大,能够容纳更多的人来
膜拜他。请问 AP的宫殿最后会有多大(宫殿必须是矩形)?
【输入】
第一行为 N和 M。之后 N 行,每行 M 个数,描述的空地的海拔(取值范围在 longint
范围内)。
【输出】
输出一行,表示宫殿最大面积。
【输出输出样例】
long.in long.out
3 2 4
4 0
-10 8
-2 -2
4
【数据规模】
对于 30%的数据,N,M≤50;
对于 100%的数据,N,M≤200;
真的是用单调栈,2333。
先把这个矩阵压成一维(如果不知道怎么做,可以看看我的伪题解)。
然后就会存在一个问题,最长连续和为正的序列。
之前的做法是用前缀和,然后枚举开始和结尾,
当然这样会超时,于是就想到了用单调栈。
就是这样。
代码是我写的:
1 #include <iostream> 2 #include <fstream> 3 #include <cstdlib> 4 #include <iomanip> 5 #include <cstring> 6 /* run this program using the console pauser or add your own getch, system("pause") or input loop */ 7 8 using namespace std; 9 ifstream fin("long.in"); 10 ofstream fout("long.out"); 11 12 int cnt_he,cnt_zo; 13 long long int jv_zhui[205][205]={0}; 14 long long int sum[205]={0}; 15 long long int qianz[205]={0}; 16 int zhan[205]={0}; 17 int zhi=0; 18 19 int xun(int z_zo,int gs,int ks); 20 int findz(int sze); 21 22 23 int xun(int z_zo,int gs,int ks){ 24 int zd=0,zd1=0; 25 memset(qianz,0,sizeof(qianz)); 26 for(int x=1;x<=cnt_he;x++)qianz[x]=qianz[x-1]+jv_zhui[x][ks+gs-1]-jv_zhui[x][ks-1]; 27 long long tem=0; 28 qianz[0]=0x7fffffff; 29 memset(zhan,0,sizeof(zhan)); 30 zhan[0]=0; 31 zhi=0; 32 for(int x=1;x<=cnt_he;x++){ 33 tem=qianz[x]; 34 //cout<<qianz[x]<<" "; 35 if(tem>0)zd=max(zd,x); 36 else{ 37 int wei=findz(x); 38 //cout<<wei<<endl; 39 zd=max(zd,x-wei); 40 } 41 if(qianz[zhan[zhi]]>qianz[x]){ 42 zhan[++zhi]=x; 43 } 44 } 45 return zd; 46 } 47 48 49 int findz(int sze){ 50 if(zhi==0)return sze+1; 51 int ks=1,js=zhi,tem=0x7fffffff; 52 while(ks<=js){ 53 int mid=(ks+js)/2; 54 if(qianz[sze]-qianz[zhan[mid]]>0){ 55 tem=min(tem,zhan[mid]); 56 js=mid-1; 57 } 58 else ks=mid+1; 59 } 60 return tem; 61 } 62 63 64 int main(int argc, char *argv[]) { 65 fin>>cnt_he>>cnt_zo; 66 for(int x=1;x<=cnt_he;x++){ 67 for(int y=1;y<=cnt_zo;y++){ 68 long long a=0; 69 fin>>a; 70 jv_zhui[x][y]=jv_zhui[x][y-1]+a; 71 } 72 } 73 74 int max_mian=0; 75 for(int x=cnt_zo;x>=1;x--){ 76 for(int y=1;y<=cnt_zo-x+1;y++){ 77 int zo=xun(max_mian/x,x,y); 78 max_mian=max(max_mian,x*zo); 79 } 80 } 81 cout<<max_mian; 82 fout<<max_mian; 83 84 85 return 0; 86 }