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; }