2019牛客多校2 H Second Large Rectangle(悬线法)
题意:
求第二大子矩形
思路:
设最大子矩形x*y,第二大子矩形一定在一下情况中
(x-1)*y
x*(y-1)
其他最大子矩形候选者
注意去重手法
代码:
#include<iostream> #include<cstdio> #include<algorithm> //#include<cmath> #include<cstring> #include<string> #include<stack> #include<queue> #include<deque> #include<set> #include<vector> #include<map> #define fst first #define sc second #define pb push_back #define mem(a,b) memset(a,b,sizeof(a)) #define lson l,mid,root<<1 #define rson mid+1,r,root<<1|1 #define lc root<<1 #define rc root<<1|1 using namespace std; typedef double db; typedef long double ldb; typedef long long ll; typedef unsigned long long ull; typedef pair<int,int> PI; typedef pair<ll,ll> PLL; const db eps = 1e-6; const int mod = 1e9+7; const int maxn = 1e4+100; const int maxm = 2e6+100; const int inf = 0x3f3f3f3f; //const db pi = acos(-1.0); int a[1111][1111]; int l[1111][1111]; int r[1111][1111]; multiset<int>ans; int h[1111][1111]; int lft[1111][1111]; int rt[1111][1111]; int n, m; int main(){ scanf("%d %d" ,&n, &m); for(int i = 1; i <= n; i++){ for(int j = 1; j <= m; j++){ scanf("%1d",&a[i][j]); } } for(int i = 1; i <= n; i++){ int tmp = 0; for(int j = 1; j <= m; j++){ if(a[i][j]==0)tmp=j; lft[i][j]=tmp; } tmp=m+1; for(int j = m; j >= 1; j--){ if(a[i][j]==0)tmp=j; rt[i][j]=tmp; } } PI mx=make_pair(-1,-1); int up = -1; int mxs = 0; for(int i = 1; i <= n; i++){ for(int j = 1; j <= m; j++){ if(i==1||a[i-1][j]==0)h[i][j]=1; else h[i][j]=h[i-1][j]+1; if(h[i][j]==1){ l[i][j] = lft[i][j]; r[i][j] = rt[i][j]; } else{ l[i][j] = max(l[i-1][j],lft[i][j]); r[i][j] = min(r[i-1][j], rt[i][j]); } if(a[i][j]==0)continue; int res = (r[i][j]-l[i][j]-1)*h[i][j]; if(res>mxs){ mxs=res; mx = make_pair(i,j);up=i-h[i][j]+1; } } } int ans = max((r[mx.fst][mx.sc]-l[mx.fst][mx.sc]-1)*(h[mx.fst][mx.sc]-1),(r[mx.fst][mx.sc]-l[mx.fst][mx.sc]-2)*h[mx.fst][mx.sc]); //printf("%d\n",ans); for(int i = 1; i <= n; i++){ for(int j = 1; j <= m; j++){ if(l[i][j]==l[mx.fst][mx.sc]&&r[i][j]==r[mx.fst][mx.sc]&&i-h[i][j]+1==up)continue; int sum = (r[i][j]-l[i][j]-1)*h[i][j]; if(sum>ans){ ans=sum; } } } printf("%d",ans); return 0; } /* 1 2 11 3 3 110 111 011 3 3 111 011 011 1 4 1011 3 4 1101 0111 1111 7 8 11110000 11110000 00000111 01110111 01110111 01110000 00000000 4 4 1111 1111 1111 1111 3 3 111 010 010 2 6 010011 001111 3 3 011 111 111 */