JOI2017 JOIOI王国
作者:互联网
JOIOI王国 JOI2017 题解
因为题目是最大值最小,所以考虑二分答案,观察题目中的划分方案可以发现,最后的划分的那条边界线一定是最后分成了个梯形的形状,即分界点单调不降或不升。因为是要二分,所以我们假设王国格子的最小值在左边,最大值在右边,分界线划出来的左边是个下梯形,即上底大于等于下底。那么直接一行一行的扫过去,比较一下就行(具体的康康代码)
问题就是,这种划分情况只是我们假设的(最小值左最大值右下梯形),所以每次把这个矩形顺时针旋转90°,转四次,每次二分一下就行
点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=2005;
const int inf=0x3f3f3f3f;
inline int read()
{
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')
f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=(x<<3)+(x<<1)+(ch^48);
ch=getchar();
}
return x*f;
}
int n,m;
int a[maxn][maxn][3],op,maxv=-inf,minv=inf;
bool check(int x)
{
int lst=m;
for(int i=1;i<=n;i++)
{
int nw=lst;
for(int j=1;j<=lst;j++)
{
if(a[i][j][op]-minv>x)
{
nw=j-1;
break;
}
}
for(int j=nw+1;j<=m;j++)
if(maxv-a[i][j][op]>x)
return false;
lst=nw;
}
return true;
}
int main()
{
freopen("joioi.in","r",stdin);
freopen("joioi.out","w",stdout);
n=read(),m=read();
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
a[i][j][0]=read();
maxv=max(maxv,a[i][j][0]);
minv=min(minv,a[i][j][0]);
}
}
int ans=inf;
for(int i=1;i<=4;i++)
{
int l=0,r=maxv-minv,res=0;
while(l<=r)
{
int mid=(l+r)>>1;
if(check(mid))
{
r=mid-1;
res=mid;
}
else
l=mid+1;
}
ans=min(ans,res);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
a[m-j+1][i][op^1]=a[i][j][op];
op^=1;
swap(n,m);
}
cout<<ans<<endl;
return 0;
}
标签:ch,JOI2017,int,最大值,mid,JOIOI,read,王国,nw 来源: https://www.cnblogs.com/zxi8-may/p/16300736.html