题解:P10965 Largest Submatrix
题意
有一个
思路
不难看出,这题其实就是把 P4147 玉蟾宫跑三遍。
其实这题就是单调栈求最大子矩阵的板子题。
由于
我们可以先对于每一个位置,求出从这个位置往下延伸,分别能得到多少个连续的
这样分别得到三个矩阵后,我们就可以考虑分别求出所有元素是
首先了解一下单调栈的定义:单调栈就是指栈内所有元素都是单调递增或单调递减的。例如 1 2 5 10 100 1000 就是一个单调递增的数列。(单调递增与单调不降是有区别的,注意区分)
对于单调栈求最大子矩阵,我们用的是单调递增的栈。我们对于每一行遍历一遍
int js=0;
while(!q.empty()&&h[i][j]<=q.top().h){
ans=max(ans,q.top().h*(js+q.top().w));
js+=q.top().w;
q.pop();
}
q.push({h[i][j],1+js});
这段代码实现的是:对于栈中的每一个高度,假如当前压入栈中的高度比它低,那么以它为高的最大矩形是一定无法继续向后延伸的,于是就可以将它弹出,计算一遍以它为高的矩阵大小,然而进去的小的高度的矩形是可以向高的下面延伸的,所以宽度要增加上以高的高度为高的矩形的宽度,也就是累加的
最后跑三遍单调栈分别求出全为
代码
#include<bits/stdc++.h>
using namespace std;
char a[1001][1001];
int h1[1001][1001];
int h2[1001][1001];
int h3[1001][1001];
struct Node{
int h,w;
};
stack<Node>q;
int ans=0;
int main(){
int n,m;
while(cin>>n>>m){
ans=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
h1[i][j]=h2[i][j]=h3[i][j]=0;
cin>>a[i][j];
}
}
for(int i=1;i<=n;i++){//统计往下延伸的数组
for(int j=1;j<=m;j++){
if(h1[i][j]==0&&a[i][j]!='x'&&a[i][j]!='b'&&a[i][j]!='c'){
int js=0;
int x=i;
int y=j;
while(a[x][y]!='x'&&x>=1&&a[x][y]!='b'&&a[x][y]!='c'){
h1[x][y]=++js;
x--;
}
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(h2[i][j]==0&&a[i][j]!='y'&&a[i][j]!='a'&&a[i][j]!='c'){
int js=0;
int x=i;
int y=j;
while(a[x][y]!='y'&&x>=1&&a[x][y]!='a'&&a[x][y]!='c'){
h2[x][y]=++js;
x--;
}
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(h3[i][j]==0&&a[i][j]!='w'&&a[i][j]!='b'&&a[i][j]!='a'){
int js=0;
int x=i;
int y=j;
while(a[x][y]!='w'&&x>=1&&a[x][y]!='b'&&a[x][y]!='a'){
h3[x][y]=++js;
x--;
}
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(q.empty()||h1[i][j]>q.top().h){//跑单调栈
q.push({h1[i][j],1});
}
else{
int js=0;
while(!q.empty()&&h1[i][j]<=q.top().h){
ans=max(ans,q.top().h*(js+q.top().w));
js+=q.top().w;
q.pop();
}
q.push({h1[i][j],1+js});
}
}
int js=0;
while(!q.empty()){
ans=max(ans,q.top().h*(js+q.top().w));
js+=q.top().w;
q.pop();
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(q.empty()||h2[i][j]>q.top().h){
q.push({h2[i][j],1});
}
else{
int js=0;
while(!q.empty()&&h2[i][j]<=q.top().h){
ans=max(ans,q.top().h*(js+q.top().w));
js+=q.top().w;
q.pop();
}
q.push({h2[i][j],1+js});
}
}
int js=0;
while(!q.empty()){
ans=max(ans,q.top().h*(js+q.top().w));
js+=q.top().w;
q.pop();
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(q.empty()||h3[i][j]>q.top().h){
q.push({h3[i][j],1});
}
else{
int js=0;
while(!q.empty()&&h3[i][j]<=q.top().h){
ans=max(ans,q.top().h*(js+q.top().w));
js+=q.top().w;
q.pop();
}
q.push({h3[i][j],1+js});
}
}
int js=0;
while(!q.empty()){
ans=max(ans,q.top().h*(js+q.top().w));
js+=q.top().w;
q.pop();
}
}
printf("%d\n",ans);
}
return 0;
}
AC 记录。