Main idea:
Given a matrix of n*m containing only 0 1, we can find the area of the second largest total 1.
sample input
1 2
01
output
0
input
1 3
101
output
1
To find the second largest all 1 matrix, we first need to determine how to find each matrix. We determine 1 on each column. If there is 1 in the current column, then we put 1 + 1 on the corresponding column of the following row.
0001 0011 0011 0000
It can be pre processed into
0001 0012 0023 0000
Each number indicates that there are several 1's above it, so you can sort the columns later, and then find the column with the most 1. Because the column with the most 1 is found first, if the remaining adjacent column also has 1, it must be smaller than this column, so that it can always form a rectangle on the small column, and the length can be maintained by parallel query set, so that the length can be found at each adjacent position. Then we need to find the second largest rectangle. What condition does the second largest rectangle satisfy? In fact, we only need to find each rectangle that is not in the same connection and buckle a point on the periphery of each rectangle in each connection, so that we can find each independently connected rectangle and the length-1 or width-1 of this rectangle, and only save the largest and the second largest, the most Then output the second largest.
#include<cstdio> #include<iostream> #include<algorithm> using namespace std; #define F first #define S second typedef pair<int,int> p; int n,m,maxa,maxb; char s[1010]; int a[1010][1010],t[1010][1010]; int vis[1010],sz[1010],pre[1010]; p h[1010]; void read(){ scanf("%d %d",&n,&m); for(int i=1;i<=n;i++){ cin >> s+1; for(int j=1;j<=m;j++) a[i][j]=(s[j]=='0')?0:1; } } void work1(){ for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){ t[i][j]=(a[i][j]==1)?t[i-1][j]+1:0; //Preprocess each column 1 } } } int ffind(int x){ return x==pre[x]?x:pre[x]=ffind(pre[x]); //Maximum length of concurrent query set maintenance } void _union(int x,int y){ pre[y]=x; sz[x]+=sz[y]; } void work(int x){ //Save only the largest and the second largest if(x>maxa) maxb=maxa,maxa=x; else if(x>maxb) maxb = x; } int main(){ read(); work1(); for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++) pre[j]=j,sz[j]=1,vis[j]=0,h[j]=(p){t[i][j],j}; sort(h+1,h+m+1); for(int j=m;j;j--){ int x=h[j].S; vis[x]=1; if(vis[x-1]) _union(ffind(x),ffind(x-1));//If the left and right sides of the current size point have been traversed before, then the large side must satisfy the small side if(vis[x+1]) _union(ffind(x),ffind(x+1)); int len = sz[ffind(x)]; work(len*h[j].F); //Here we can find the second largest one, just click a point, x y, X (Y-1), (x-1) y work(len*(h[j].F-1)); work((len-1)*h[j].F); } } cout<<maxb<<endl; return 0; }