luogu_3933 Chtholly Nota Seniorious
题目大意为将矩阵划分为两部分,要求两部分极差的最大值最小,考虑二分答案
且分界线要求单调递增或单调递减,方向不限,考虑矩阵旋转
其中矩阵旋转通过改变分界线枚举方向实现
因为只有两个部分,因此只需标记其中一部分即可
最大值最小值一定不在同一部分,因此要分别考虑最大/最小值在当前部分
蓝题
以上
/*
time:2019/07/16
author:weiya040214
problem:Chtholly Nota Seniorious
OJ:luogu
*/
#include<bits/stdc++.h>
#define ll long long
#define maxn 2100
#define INF 2147483647
using namespace std;
int n,m;
bool occ[maxn][maxn];
int a[maxn][maxn];
int minn=INF,maxx=-1;
bool nota(int mid)
{
int sa=INF,sb=INF,ba=-1,bb=-1;
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
{
if (occ[i][j])
{
ba=max(ba,a[i][j]);
sa=min(sa,a[i][j]);
}
else
{
bb=max(bb,a[i][j]);
sb=min(sb,a[i][j]);
}
}
if (max(ba-sa,bb-sb)<=mid)
return 1;
return 0;
}
bool chtholly(int mid)
{
// 右上--左下 (左)
int l=m;
for(int i=1;i<=n;i++)
{
int k=0;
for (int j=1;j<=l;j++)
if (maxx-a[i][j]<=mid)
{
occ[i][j]=1;
k++;
}
else
break;
l=k;
}
if (nota(mid))
{
return 1;
}
memset(occ,0,sizeof(occ));
l=m;
for(int i=1;i<=n;i++)
{
int k=0;
for (int j=1;j<=l;j++)
if (a[i][j]-minn<=mid)
{
occ[i][j]=1;
k++;
}
else
break;
l=k;
}
if (nota(mid))
{
return 1;
}
memset(occ,0,sizeof(occ));
//左上到右下 (右)
l=1;
for(int i=1;i<=n;i++)
{
int k=m;
for (int j=m;j>=l;j--)
if (maxx-a[i][j]<=mid)
{
occ[i][j]=1;
k--;
}
else
break;
l=k;
}
if (nota(mid))
{
return 1;
}
memset(occ,0,sizeof(occ));
l=1;
for(int i=1;i<=n;i++)
{
int k=m;
for (int j=m;j>=l;j--)
if (a[i][j]-minn<=mid)
{
occ[i][j]=1;
k--;
}
else
break;
l=k;
}
if (nota(mid))
{
return 1;
}
memset(occ,0,sizeof(occ));
//左上到右下(左)
l=m;
for(int i=n;i>=1;i--)
{
int k=0;
for (int j=1;j<=l;j++)
if (maxx-a[i][j]<=mid)
{
occ[i][j]=1;
k++;
}
else
break;
l=k;
}
if (nota(mid))
{
return 1;
}
memset(occ,0,sizeof(occ));
l=m;
for(int i=n;i>=1;i--)
{
int k=0;
for (int j=1;j<=l;j++)
if (a[i][j]-minn<=mid)
{
occ[i][j]=1;
k++;
}
else
break;
l=k;
}
if (nota(mid))
{
return 1;
}
memset(occ,0,sizeof(occ));
//右上到左下(右)
l=1;
for(int i=n;i>=1;i--)
{
int k=m;
for (int j=m;j>=l;j--)
if (maxx-a[i][j]<=mid)
{
occ[i][j]=1;
k--;
}
else
break;
l=k;
}
if (nota(mid))
{
return 1;
}
memset(occ,0,sizeof(occ));
l=1;
for(int i=n;i>=1;i--)
{
int k=m;
for (int j=m;j>=l;j--)
if (a[i][j]-minn<=mid)
{
occ[i][j]=1;
k--;
}
else
break;
l=k;
}
if (nota(mid))
{
return 1;
}
memset(occ,0,sizeof(occ));
return 0;
}
int main()
{
cin>>n>>m;
for (int i=1;i<=n;i++)
for (int j=1;j<=m;j++)
{
scanf("%d",&a[i][j]);
maxx=max(maxx,a[i][j]);
minn=min(minn,a[i][j]);
}
int l,r,ans;
r=maxx-minn;
l=0;
ans=-1;
while (l<r)
{
int mid=(l+r)/2;
// cout<<"hah"<<chtholly(mid)<<endl;
if (chtholly(mid))
{
// cout<<mid<<' ';
ans=mid;
r=mid-1;
}
else
l=mid+1;
}
cout<<ans;
return 0;
}