submatrix |
难度级别: A; 编程语言:不限;运行时间限制:2000ms; 运行空间限制:131072KB; 代码长度限制:102400B |
试题描述
|
|
输入
|
第一行,两个整数N, M。
接下来的N行,每行M个整数,表示矩阵中的元素。 |
输出
|
N×M行,每行一个整数,其中第i行的整数表示如果小A选择的子矩阵权值为i,他选择的子矩阵的种类数。
|
输入示例
|
2 3
2 5 1 6 3 4 |
输出示例
|
6
4 5 1 1 1 |
其他说明
|
对于30%的数据,1<=N, M<=50;
对于全部的数据,1<=N, M<=300。 |
题解:%%%郑爷,先考虑一维,用单调栈维护一下可以到左边右边,更新答案。对于二维,把一维拍扁就可以了。。。。记得是取最小值。。。
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<algorithm> 5 #include<queue> 6 #include<cstring> 7 #define PAU putchar(' ') 8 #define ENT putchar(' ') 9 using namespace std; 10 const int maxn=300+10,maxans=90000+10,inf=-1u>>1; 11 int A[maxn][maxn],mi[maxn],R[maxn],L[maxn],s[maxn],pos[maxn],p[maxans],n,m; 12 inline int read(){ 13 int x=0,sig=1;char ch=getchar(); 14 for(;!isdigit(ch);ch=getchar())if(ch=='-')sig=0; 15 for(;isdigit(ch);ch=getchar())x=10*x+ch-'0'; 16 return sig?x:-x; 17 } 18 inline void write(int x){ 19 if(x==0){putchar('0');return;}if(x<0)putchar('-'),x=-x; 20 int len=0,buf[15];while(x)buf[len++]=x%10,x/=10; 21 for(int i=len-1;i>=0;i--)putchar(buf[i]+'0');return; 22 } 23 void init(){ 24 n=read();m=read(); 25 for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)A[i][j]=read(); 26 for(int i=1;i<=n;i++){ 27 for(int j=1;j<=m;j++)mi[j]=inf; 28 for(int j=i;j<=n;j++){ 29 for(int k=1;k<=m;k++)mi[k]=min(mi[k],A[j][k]);int top=0; 30 for(int k=1;k<=m;k++){//正 31 while(top&&(mi[k]<s[top]))R[pos[top--]]=k-1; 32 s[++top]=mi[pos[top]=k]; 33 }while(top)R[pos[top--]]=m; 34 for(int k=m;k>=1;k--){//反 35 while(top&&(mi[k]<s[top]))L[pos[top--]]=k+1; 36 s[++top]=mi[pos[top]=k]; 37 }while(top)L[pos[top--]]=1; 38 for(int k=1;k<=m;k++)p[mi[k]]+=(R[k]-k+1)*(k-L[k]+1); 39 } 40 }int all=n*m;for(int i=1;i<=all;i++)write(p[i]),ENT; 41 return; 42 } 43 void work(){ 44 return; 45 } 46 void print(){ 47 return; 48 } 49 int main(){init();work();print();return 0;}