早上打一半就回家了...
T1傻逼题不说了...而且我的写法比题解要傻逼很多T T
T2可以发现,我们强制最大值所在的块是以左上为边界的倒三角,然后旋转4次就可以遍历所有的情况。所以二分极差,把最大值所能扩展到的(mp[i][j]+mid>=mx)最大倒三角求出来,剩下的数减去最小值判断一下是否小于等于极差,如果是的话答案可行。
#include<iostream> #include<cstring> #include<cstdlib> #include<cstdio> #include<algorithm> #define ll long long using namespace std; const int maxn=2010,inf=1e9; int mn,mx; int n[4],m[4],mp[4][maxn][maxn]; bool v[maxn][maxn]; void read(int &k) { int f=1;k=0;char c=getchar(); while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); while(c<='9'&&c>='0')k=k*10+c-'0',c=getchar(); k*=f; } void rotate(int x,int y) { for(int i=1;i<=n[x];i++) for(int j=1;j<=m[x];j++) mp[y][j][n[x]-i+1]=mp[x][i][j]; n[y]=m[x];m[y]=n[x]; } bool check(int x,int mid) { memset(v,0,sizeof(v)); int now=m[x]; for(int i=1;i<=n[x];i++) for(int j=1;j<=now;j++) if(mp[x][i][j]+mid<mx){now=j-1;break;} else v[i][j]=1; for(int i=n[x];i;i--) for(int j=m[x];j;j--) if(v[i][j])break; else if(mp[x][i][j]-mid>mn)return 0; return 1; } int main() { read(n[0]);read(m[0]);mn=inf; for(int i=1;i<=n[0];i++)for(int j=1;j<=m[0];j++)read(mp[0][i][j]),mx=max(mx,mp[0][i][j]),mn=min(mn,mp[0][i][j]); rotate(0,1);rotate(1,2);rotate(2,3); int l=0,r=mx-mn; while(l<r) { int mid=(l+r)>>1; if(check(0,mid)||check(1,mid)||check(2,mid)||check(3,mid))r=mid; else l=mid+1; } printf("%d\n",l); return 0; }