【字符矩阵哈希】【二分答案】【哈希表】bzoj1567 [JSOI2008]Blue Mary的战役地图

引用题解:http://hzwer.com/5153.html

当然,二分可以换成哈希表。

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
#define MOD 2501
typedef unsigned long long ull;
const ull seed1=3659,seed2=1789;
ull sum[51][51],sum2[51][51],v[MOD],pow1[51],pow2[51];
int n,ans,first[MOD],next[MOD],en;
void Insert(const ull &V)
{
	int U=(int)(V%MOD);
	v[en]=V;
	next[en]=first[U];
	first[U]=en++;
}
bool check(const int &x)
{
	memset(first,-1,sizeof(first)); en=0;
	for(int i=x;i<=n;i++)
	  for(int j=x;j<=n;j++)
	    Insert(sum[i][j]
		-sum[i-x][j]*pow1[x]
		-sum[i][j-x]*pow2[x]
		+sum[i-x][j-x]*pow1[x]*pow2[x]);
	for(int i=x;i<=n;i++)
	  for(int j=x;j<=n;j++)
	    {
	      ull t=sum2[i][j]
		  -sum2[i-x][j]*pow1[x]
		  -sum2[i][j-x]*pow2[x]
		  +sum2[i-x][j-x]*pow1[x]*pow2[x];
		  int o=(int)(t%MOD);
		  for(int i=first[o];i!=-1;i=next[i])
		    if(t==v[i])
		      return 1;
	    }
	return 0;
}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;++i)for(int j=1;j<=n;++j)
	  cin>>sum[i][j];
	for(int i=1;i<=n;++i)for(int j=1;j<=n;++j)
	  cin>>sum2[i][j];
	for(int i=1;i<=n;++i)for(int j=1;j<=n;++j)
	  sum[i][j]+=sum[i-1][j]*seed1;
	for(int i=1;i<=n;++i)for(int j=1;j<=n;++j)
	  sum[i][j]+=sum[i][j-1]*seed2;
	for(int i=1;i<=n;++i)for(int j=1;j<=n;++j)
	  sum2[i][j]+=sum2[i-1][j]*seed1;
	for(int i=1;i<=n;++i)for(int j=1;j<=n;++j)
	  sum2[i][j]+=sum2[i][j-1]*seed2;
	pow1[0]=pow2[0]=1;
    for(int i=1;i<=n;i++)
	  pow1[i]=pow1[i-1]*seed1,
	  pow2[i]=pow2[i-1]*seed2;
	int l=1,r=n;
	while(l<=r)
	  {
		int mid=l+r>>1;
		if(check(mid))
		  ans=mid,l=mid+1;
		else r=mid-1;
	  }
	printf("%d\n",ans);
	return 0;
}
时间: 2024-10-24 22:22:12

【字符矩阵哈希】【二分答案】【哈希表】bzoj1567 [JSOI2008]Blue Mary的战役地图的相关文章

BZOJ 1567 JSOI2008 Blue Mary的战役地图 Hash+二分

题目大意:给定两个矩阵,求最大公共子正方形边长 首先二分答案 然后Check的时候先把A矩阵的所有边长为x的子正方形存在哈希表里 然后枚举B矩阵的每个子正方形查找 注意二维哈希的时候横竖用的两个BASE不能一样 否则当两个矩阵关于对角线对称的时候会判断为相等 尼玛我的哈希表居然比map慢--不活了 #include<map> #include<cstdio> #include<cstring> #include<iostream> #include<a

BZOJ 1567 Blue Mary的战役地图(二维hash+二分)

题意: 求两个矩形最大公共子正方形.(n<=50) 范围这么小可以枚举子正方形的边长.那么可以对这个矩形进行二维hash,就可以在O(1)的时候求出任意子矩形的hash值.然后判断这些正方形的hash值有没有相同的 部分就行了.可以用二分来判断. 需要注意的是行和列乘的hash种子值需要不同的质数,否则可能出现冲突. 时间复杂度O(n^3logn). # include <cstdio> # include <cstring> # include <cstdlib>

bzoj1568: [JSOI2008]Blue Mary开公司 三分+二分+线段树

答案序列一定是个下凸壳,因此添加的等差数列与其之差是个单峰函数,可以先三分求出最值,再二分求出零点,然后用线段树,将得到的区间修改为一个等差数列. 这个做法应该比较好想吧,虽然比较慢…… #include<cstdio> #define Z int l=1,int r=N,int k=1 #define N 50000 #define M (l+r>>1) #define P (k<<1) #define S (k<<1|1) #define K l,r,k

【二分答案】【哈希表】【字符串哈希】bzoj2946 [Poi2000]公共串

二分答案,然后搞出hash值扔到哈希表里.期望复杂度O(n*log(n)). #include<cstdio> #include<cstring> #include<vector> using namespace std; typedef unsigned long long ull; const ull seed=29; #define MOD 2007 typedef vector<ull>::iterator VER; vector<ull>

UVA 11019 字符矩阵哈希

思路:以前没做过字符矩阵的哈希,所以这题是看别人博客写的. #pragma comment(linker, "/STACK:1024000000,1024000000") #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<map> #include<queue> #include<set>

【CodeForces】961 F. k-substrings 字符串哈希+二分

[题目]F. k-substrings [题意]给定长度为n的串S,对于S的每个k-子串$s_ks_{k+1}...s_{n-k+1},k\in[1,\left \lceil \frac{n}{2} \right \rceil]$,找到满足[奇数长度][严格子串][同时是前缀和后缀]的最长子串.n<=10^6. [算法]字符串哈希+二分 [题解]任意两个对应子串,它们有一个不变量--它们的中心一定是i和n-i+1.而且固定中心之后,能延伸的最长相等子串是可以二分+哈希得到的. 所以枚举k,二分+

POJ-2774 字符串哈希+二分

题意:给出s,t两个字符串,求最长公共子串的长度 思路:首先二分答案x,预处理出s中长度为x的子串哈希值并排序,在t中枚举起点,二分查找t[i...i+x]的哈希值 二分查找直接用binary_search()函数 复杂度其实是nlog方 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<iostream> 5 #define LL long long 6 #def

LibreOJ #2006. 「SCOI2015」小凸玩矩阵 二分答案+二分匹配

#2006. 「SCOI2015」小凸玩矩阵 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: 匿名 提交提交记录统计讨论测试数据 题目描述 小凸和小方是好朋友,小方给小凸一个 N×M N \times MN×M(N≤M N \leq MN≤M)的矩阵 A AA,要求小凸从其中选出 N NN 个数,其中任意两个数字不能在同一行或同一列,现小凸想知道选出来的 N NN 个数中第 K KK 大的数字的最小值是多少. 输入格式 第一行给出三个整数

POJ2002 二分查找&amp;哈希

问题重述: 给定整数n,以及n个点的坐标xi, yi.求这n个点可以组成的正方形的数目(每个点可重复使用). 分析: 根据正方形的性质,给定两个点就能确定可能构成的两个正方形的另外两个顶点.因此,只需要遍历所有点中的两个顶点,计算出可构成正方形的另外两个顶点的坐标,再在已知点中查找这两个点是否存在即可算出正方形数目. AC代码: 1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #inclu