【JZOJ4817】【NOIP2016提高A组五校联考4】square
题目大意:给你一个n∗mn∗m的矩阵,矩阵上有一些点是障碍,有TT次询问,每次给你一个矩形x1,y1,x2,y2x1,y1,x2,y2,你要在这个矩形内找一个最大正方形使得正方形内不包含障碍。
n,m≤1000,T≤106n,m≤1000,T≤106
Solution
假设没有给定矩形的限制,设f[i][j]f[i][j]表示以(i,j)(i,j)为右下角最大不包含障碍的正方形,转移如下:
- (i,j)(i,j)有障碍则f[i][j]=0f[i][j]=0
- (i,j)(i,j)无障碍则f[i][j]=min(f[i−1][j],f[i][j−1],f[i−1][j−1])+1f[i][j]=min(f[i−1][j],f[i][j−1],f[i−1][j−1])+1
现在有了矩形的限制,我们可以二分答案midmid,则若矩形(x1+mid−1,y1+mid−1)(x1+mid−1,y1+mid−1)到(x2,y2)(x2,y2)中ff的最大值大于等于midmid,这个midmid就是合法的了。查询范围的左上角(x1+mid−1,y1+mid−1)(x1+mid−1,y1+mid−1)相当于保证了最大的正方形不超出矩形范围。
于是用一个二维rmq维护矩阵最大值即可,时空复杂度均为O(n2log2n)O(n2log2n)。
Tips: 由于没有按题解说的开mx[10][10][N][N]
而开了mx[N][N][10][10]
,导致程序TLE。这说明多维数组把小的下标开在前面可以显著提高访问速度,涨知识了。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define rg register
using namespace std;
const int N=1007;
inline int read(){
int x=0,f=0;
char c=getchar();
for(;c<'0'||c>'9';c=getchar())if(c=='-')f=1;
for(;c>='0'&&c<='9';c=getchar())x=(x<<1)+(x<<3)+(c^'0');
return f?-x:x;
}
inline int max(int a,int b){return a>b?a:b;}
inline int min(int a,int b){return a<b?a:b;}
int n,m,T,a[N][N],f[N][N],mx[10][10][N][N],Log[N],two[10];
int x1,y1,x2,y2,l,r,mid,ans;
inline int qrymax(int x1,int y1,int x2,int y2){
int k=Log[x2-x1+1],l=Log[y2-y1+1];
return max(max(mx[k][l][x1][y1],mx[k][l][x2-two[k]+1][y2-two[l]+1]),max(mx[k][l][x1][y2-two[l]+1],mx[k][l][x2-two[k]+1][y1]));
}
int main(){
//freopen("in","r",stdin);
//freopen("square.in","r",stdin);
//freopen("square.out","w",stdout);
Log[1]=0;for(int i=2;i<=1000;++i)Log[i]=Log[i>>1]+1;
for(int i=0;i<=9;++i)two[i]=(1<<i);
n=read(),m=read();
for(rg int i=1;i<=n;++i)for(rg int j=1;j<=m;++j)a[i][j]=read();
for(rg int i=1;i<=n;++i)for(rg int j=1;j<=m;++j){
if(a[i][j])f[i][j]=min(f[i-1][j-1],min(f[i-1][j],f[i][j-1]))+1;
else f[i][j]=0;
}
for(rg int i=1;i<=n;++i)for(rg int j=1;j<=m;++j)mx[0][0][i][j]=f[i][j];
for(rg int k=0;k<=Log[n];++k)for(rg int l=0;l<=Log[m];++l){
if(k+l==0)continue;
for(rg int i=1;i+two[k]-1<=n;++i)for(rg int j=1;j+two[l]-1<=m;++j){
if(l==0)mx[k][l][i][j]=max(mx[k-1][l][i][j],mx[k-1][l][i+two[k-1]][j]);
else mx[k][l][i][j]=max(mx[k][l-1][i][j],mx[k][l-1][i][j+two[l-1]]);
}
}
T=read();
while(T--){
x1=read(),y1=read(),x2=read(),y2=read();
l=1,r=min(x2-x1+1,y2-y1+1),ans=0;
while(l<=r){
mid=l+r>>1;
if(qrymax(x1+mid-1,y1+mid-1,x2,y2)>=mid)ans=mid,l=mid+1;
else r=mid-1;
}
printf("%d\n",ans);
}
return 0;
}
作者:zjlcnblogs
出处:https://www.cnblogs.com/zjlcnblogs/p/12055698.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。