习题:JOIOI王国(二分)
Posted loney-s
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了习题:JOIOI王国(二分)相关的知识,希望对你有一定的参考价值。
题目
思路
如果我们从正向开始思考,
也就是像笔者这个蒻鸡一样开始思考DP
你就会发现每一个DP值需要有4个辅助数组来转移
而且当前的DP值对后续的DP值都还有影响
但是换一个思路思考,
很容易可以发现答案是具有单调性的
也就是说二分
最终的形状一定是一个梯形
接着你在梯形内寻找最小值,再用二分的答案求出最大值
检验的时间复杂度就为(O(n*m))
外加二分的复杂度(O(log_{maxa}))
如果是1S,还是有点卡常
但是出题人善良的开了4S
代码
#include<iostream>
#include<climits>
#include<cstring>
using namespace std;
int n,m;
int a[2005][2005];
int b[2005][2005];
int c[2005][2005];
int d[2005][2005];
int h[2005];
int minn=INT_MAX;
int maxx=INT_MIN;
int l=INT_MAX;
int r=INT_MIN;
int mid;
bool dfs(int x,int t[2005][2005])
{
memset(h,0,sizeof(h));
h[n+1]=m;
for(int i=n;i>=1;i--)
{
while(h[i]<h[i+1]&&t[i][h[i]+1]-minn<=x)
h[i]++;
}
int minnh=INT_MAX;
for(int i=1;i<=n;i++)
for(int j=h[i]+1;j<=m;j++)
minnh=min(minnh,t[i][j]);
if(maxx-minnh<=x)
return 1;
return 0;
}
bool pd(int cnt)
{
if(dfs(cnt,a)||dfs(cnt,b)||dfs(cnt,c)||dfs(cnt,d))
return 1;
return 0;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cin>>a[i][j];
d[i][j]=c[i][j]=b[i][j]=a[i][j];
minn=min(minn,a[i][j]);
maxx=max(maxx,a[i][j]);
}
}
for(int i=1;i<=n/2;i++)
swap(b[i],b[n-i+1]);
for(int i=1;i<=n/2;i++)
swap(c[i],c[n-i+1]);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m/2;j++)
{
swap(c[i][j],c[i][m-j+1]);
swap(d[i][j],d[i][m-j+1]);
}
}
l=0;
r=maxx-minn;
while(l<r)
{
mid=(1ll*l+r)>>1;
if(pd(mid))
r=mid;
else
l=mid+1;
}
cout<<l;
return 0;
}
以上是关于习题:JOIOI王国(二分)的主要内容,如果未能解决你的问题,请参考以下文章
loj#2334 「JOI 2017 Final」JOIOI 王国