因为是最小值的最大值,首先我们想到用二分来查找答案。
剩下的就是实现判断mid是否可行的方法。
我们用vis[i][j]表示是否某行的i,j是大于等于mid的。
当下次出现i,j便说明2行组成一个矩形是可行的。
for(int i=1;i<=n;i++){ cnt=0; for(int j=1;j<=m;j++) if(a[i][j]>=mid){cnt++;p[cnt]=j;} int ax=0; for(int j=1;j<=cnt;j++) for(int k=1;k<j;k++){ if(vis[p[k]][p[j]])return 1; vis[p[k]][p[j]]=1; }
复杂度;i,j最多的组合是n*(n-1)/2。判断的复杂度近似可以看成n*m.
总复杂度为o(nm*log a[][])
#include<bits/stdc++.h> using namespace std; const int N=1030; int mid,l,r,m,n,p[N],jj[N],a[N][N],vis[N][N],miner=1e9,maxer; bool az(){ memset(vis,0,sizeof(vis)); int cnt=0; for(int i=1;i<=n;i++){ cnt=0; for(int j=1;j<=m;j++) if(a[i][j]>=mid){cnt++;p[cnt]=j;} int ax=0; for(int j=1;j<=cnt;j++) for(int k=1;k<j;k++){ if(vis[p[k]][p[j]])return 1; vis[p[k]][p[j]]=1; } } return 0; } int main() { //freopen("p.in","r",stdin); scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) for(int j=1;j<=m;j++){ scanf("%d",&a[i][j]); miner=min(miner,a[i][j]); maxer=max(maxer,a[i][j]); } l=miner;r=maxer; while(l<r){ mid=l+(r-l+1)/2; if(az())l=mid; else r=mid-1; } cout<<r; return 0; }
实现查找满足条件的最大值
while(l<r){ mid=l+(r-l+1)/2; if(az())l=mid; else r=mid-1; }