BZOJ1567 [JSOI2008]Blue Mary的战役地图 二分答案 哈希
欢迎访问~原文出处——博客园-zhouzhendong
去博客园看该题解
题目传送门 - BZOJ1567
题意概括
给出两个n*n的数字矩阵,问最大公共正方形边长。
题解
先二分答案一个m,对于每一个m,哈希大矩阵中每一个位置上的边长为m的正方形,然后排序,lower_bound一下判定即可。
鬼畜的是,我的代码在BZOJ上面过去了,but和hzwer大佬(Orz)的代码对拍没有过去,不知道怎么回事……
代码
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
using namespace std;
typedef long long LL;
const int N=50+5;
LL n,a[N][N],b[N][N],a1[N][N],a2[N][N],b1[N][N],b2[N][N],A[N*N],B[N*N];
bool check(LL m){
LL mod=2333333333LL,p=1000000007LL,pm=1;
for (int i=1;i<=m;i++)
pm=pm*p%mod;
memset(a1,0,sizeof a1);
memset(a2,0,sizeof a2);
memset(b1,0,sizeof b1);
memset(b2,0,sizeof b2);
memset(A,0,sizeof A);
memset(B,0,sizeof B);
for (int i=1;i<=n;i++)
for (int j=1;j+m-1<=n;j++)
for (int k=1;k<=m;k++)
a1[i][j]=(a1[i][j]*p+a[i][j+k-1])%mod;
for (int i=1;i+m-1<=n;i++)
for (int j=1;j+m-1<=n;j++)
for (int k=1;k<=m;k++)
a2[i][j]=(a2[i][j]*pm+a1[i+k-1][j])%mod;
for (int i=1;i<=n;i++)
for (int j=1;j+m-1<=n;j++)
for (int k=1;k<=m;k++)
b1[i][j]=(b1[i][j]*p+b[i][j+k-1])%mod;
for (int i=1;i+m-1<=n;i++)
for (int j=1;j+m-1<=n;j++)
for (int k=1;k<=m;k++)
b2[i][j]=(b2[i][j]*pm+b1[i+k-1][j])%mod;
int tot=0;
for (int i=1;i+m-1<=n;i++)
for (int j=1;j+m-1<=n;j++)
A[++tot]=a2[i][j],B[tot]=b2[i][j];
sort(A+1,A+tot+1);
sort(B+1,B+tot+1);
for (int i=1;i<=tot;i++)
if (A[lower_bound(A+1,A+tot+1,B[i])-A]==B[i])
return 1;
return 0;
}
int main(){
scanf("%lld",&n);
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
scanf("%lld",&a[i][j]),a[i][j]+=1LL<<31;
for (int i=1;i<=n;i++)
for (int j=1;j<=n;j++)
scanf("%lld",&b[i][j]),b[i][j]+=1LL<<31;
LL le=1,ri=n,mid,ans=0;
while (le<=ri){
mid=(le+ri)>>1;
if (check(mid))
le=mid+1,ans=mid;
else
ri=mid-1;
}
printf("%lld",ans);
return 0;
}

浙公网安备 33010602011771号