最显然易见的做法就是枚举一条对角线的两个端点,不过,这样是过不了的。然后,就需要一些技巧了。
我们先贪心地想一想,如果第一次选最大的两个点算,当然是不行的。。
但我们多做几次,是不是正确率就会变高呢。答案是显然的,我们就取出最大的一些数来算,这样就成O(num^2)了,之后,这个num^2如何选取呢。
如果在考场上,就按极限取吧,只要不超时就行。这样如果我们的想法是对的,就会A。
选取4*n其实就行了。但是,如何证明?emmm,我不会呀,感性认识???或者可以对对拍。
#include<bits/stdc++.h>
#define MIN(a,b,c,d) min(b,min(a,min(c,d)))
using namespace std;
int n,m,tot,cnt,ans,mn;
int s[1005][1005];
struct position{
int i,j,v;
bool operator < (const position &A) const{
return v>A.v;
}
};position tmp[1000*1000+5],A[1000*1000+5];
inline char nc()
{
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
int x=0,f=1;
char c=nc();
for(;!(c<='9'&&c>='0');c=nc())if(c=='-')f=-1;
for(;c<='9'&&c>='0';c=nc())x=x*10+c-'0';
return x*f;
}
int main()
{
freopen("in.txt","r",stdin);
n=read(),m=read();tot=min(4*n,m*n);
for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)
s[i][j]=read(),tmp[++cnt].i=i,tmp[cnt].j=j,tmp[cnt].v=s[i][j];
sort(tmp+1,tmp+cnt);
for(int i=1;i<=tot;i++)A[i]=tmp[i];
for(int i=1;i<=tot;i++)
for(int j=1;j<i;j++)
if(A[i].i!=A[j].i&&A[i].j!=A[j].j)
{
mn=MIN(s[A[i].i][A[i].j],s[A[j].i][A[j].j],s[A[i].i][A[j].j],s[A[j].i][A[i].j]);
ans=max(ans,mn);
}
cout<<ans;
return 0;
}