子正方形【二维hash】【二分】

>Link

ybtoj子正方形


>解题思路

其实跟这道题差不多,甚至更简单,因为不用考虑镜面翻转


>代码

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 100
#define ull unsigned long long
using namespace std;

const ull p1 = 100003, p2 = 100009;
int n, ans;
ull a[N][N], b[N][N], ha[N][N], hb[N][N], l1[N], l2[N];

ull aska (int x, int y, int xx, int yy)
{
	return
	  ha[xx][yy] - ha[x - 1][yy] * l2[xx - x + 1]
	  - ha[xx][y - 1] * l1[yy - y + 1]
	  + ha[x - 1][y - 1] * l1[yy - y + 1] * l2[xx - x + 1];
}
ull askb (int x, int y, int xx, int yy)
{
	return
	  hb[xx][yy] - hb[x - 1][yy] * l2[xx - x + 1]
	  - hb[xx][y - 1] * l1[yy - y + 1]
	  + hb[x - 1][y - 1] * l1[yy - y + 1] * l2[xx - x + 1];
}
void work (int x1, int y1, int x2, int y2)
{
	int l = 0, r = n, mid;
	while (l <= r)
	{
		mid = (l + r) / 2;
		int x, y, xx, yy;
		x = x1 - mid, y = y1 - mid;
		xx = x1 + mid, yy = y1 + mid;
		if (x < 1 || y < 1 || xx > n || yy > n)
		{r = mid - 1; continue;}
		ull r1 = aska (x, y, xx, yy);
		x = x2 - mid, y = y2 - mid;
		xx = x2 + mid, yy = y2 + mid;
		if (x < 1 || y < 1 || xx > n || yy > n)
		{r = mid - 1; continue;}
		ull r2 = askb (x, y, xx, yy);
		
		if (r1 == r2)
		  l = mid + 1, ans = max (ans, 2 * mid + 1);
		else r = mid - 1;
	}
	l = 0, r = n;
	while (l <= r)
	{
		mid = (l + r) / 2;
		int x, y, xx, yy;
		x = x1 - mid + 1, y = y1 - mid + 1;
		xx = x1 + mid, yy = y1 + mid;
		if (x < 1 || y < 1 || xx > n || yy > n)
		{r = mid - 1; continue;}
		ull r1 = aska (x, y, xx, yy);
		x = x2 - mid + 1, y = y2 - mid + 1;
		xx = x2 + mid, yy = y2 + mid;
		if (x < 1 || y < 1 || xx > n || yy > n)
		{r = mid - 1; continue;}
		ull r2 = askb (x, y, xx, yy);
		
		if (r1 == r2)
		  l = mid + 1, ans = max (ans, 2 * mid);
		else r = mid - 1;
	}
}

int main()
{
	scanf ("%d", &n);
	for (int i = 1; i <= n; i++)
	  for (int j = 1; j <= n; j++) scanf ("%lld", &a[i][j]);
	for (int i = 1; i <= n; i++)
	  for (int j = 1; j <= n; j++) scanf ("%lld", &b[i][j]);
	for (int i = 1; i <= n; i++)
	  for (int j = 1; j <= n; j++)
	  {
	  	ha[i][j] = ha[i][j - 1] * p1 + a[i][j];
	  	hb[i][j] = hb[i][j - 1] * p1 + b[i][j];
	  }
	for (int i = 1; i <= n; i++)
	  for (int j = 1; j <= n; j++)
	  {
	  	ha[i][j] += ha[i - 1][j] * p2;
	  	hb[i][j] += hb[i - 1][j] * p2;
	  }
	l1[0] = l2[0] = 1;
	for (int i = 1; i <= n; i++)
	  l1[i] = l1[i - 1] * p1, l2[i] = l2[i - 1] * p2;
	for (int x1 = 1; x1 <= n; x1++)
	  for (int y1 = 1; y1 <= n; y1++)
	    for (int x2 = 1; x2 <= n; x2++)
	      for (int y2 = 1; y2 <= n; y2++)
	        work (x1, y1, x2, y2);
	printf ("%d", ans);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
二维哈希封装模板通常在需要将二维数据结构与哈希表功能结合起来的场景下使用,尤其是在需要快速查找、插入和删除元素的情况下。这种结构可以大大提高数据处理效率。 ### 思想概述 二维哈希封装模板的基本思想是创建一个类,该类内部包含一个哈希表,用于存储键值对,并允许通过两个维度的索引来访问这些键值对。这种设计使得用户可以通过一组有序的键(例如坐标)来直接定位到特定的数据位置。 ### 实现细节 在实现过程中,关键在于如何设计哈希函数,使其能够有效地利用空间并减少碰撞(即不同的键映射到相同的哈希值)。常见的做法包括: 1. **哈希函数**:设计一种算法,将二维坐标转换为唯一的整数,作为哈希表的键。这通常涉及到计算两个坐标值的某种组合,比如简单相加、乘法或其他数学操作,以及可能的模运算,以确保结果保持在哈希表的范围内。 2. **负载因管理**:为了保持良好的性能,通常需要控制哈希表的负载因(即已使用的条目占总容量的比例),并在达到某个阈值时动态调整哈希表的大小。 3. **冲突解决策略**:当不同的键映射到同一哈希值时,需要有机制来解决冲突,如链地址法、开放寻址等。 4. **封装**:提供方便的操作接口,允许用户以直观的方式添加、查询和移除元素,而不需要深入了解底层的哈希实现细节。 ### 示例应用 二维哈希表可以应用于多种场景,如地图搜索、游戏中的网格管理、数据库索引优化等。例如,在游戏中,每个玩家的位置可以用二维坐标表示,使用二维哈希表可以高效地更新和查询玩家的位置信息。 ### 相关问题: 1. 为什么选择特定的哈希函数来计算二维坐标? 2. 在什么情况下会考虑增加哈希表的大小? 3. 二维哈希表如何处理不同维度之间的关联和独立性问题?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值