【五一省选集训day4】Grid Game
首先发现 \(n,m\le 2000\),可以考虑枚举正方形左上端点 \((x_0,y_0)\)。
对于一个边长为 \(len\) 的合法的正方形,如果 \(len=k\) 这个正方形全黑,需要特判,否则它至少有一个白点。
我们惊奇地发现,对于这样的其中一个白点,它所在的那一列一定存在恰好 \(k\) 个黑点,且这 \(k\) 个黑点所在的行是黑的。它所在的那一行一定存在恰好 \(k\) 个黑点,且这 \(k\) 个黑点所在的列是黑的。因此,我们注意到,确定一个白点之后,我们就可以确定 \(k\) 行 \(k\) 列染色的位置了。
注意到另一个性质:对于固定左上端点,如果 \(len=l,len=r\) 都合法,那么 \(len\in [l,r]\) 都是合法的,因此我们只需求出最小的合法边长和最大合法边长。
求最小合法边长,我们可以找一个离左端点最近的白点 \((x_1,y_1)\)。这里最近是指切比雪夫距离最小,就是 \(\max\{|x_1-x_0|,|y_1-y_0|\}\) 最小。
求这个白点可以二维 DP 一下。我绝对不会写《DP 即可》。\(dp_{x_0,y_0}\) 有三种转移的可能。可能由 \(dp_{x_0+1,y_0+1}\) 转移,也可能由它正右方和正下方的最近的白点转移,取一个最近的点就好。
设这个最小距离是 \(d\),那么 \(len\ge d\) 的正方形一定包含这个白点,可以确定出染色的 \(k\) 行 \(k\) 列。要判断包含这 \(k\) 行 \(k\) 列的最小正方形是否合法,如果不合法,那么更大的正方形也不可能合法。(前提是特判掉 \(len=k\) 的情,因为即使 \(len=k\) 不合法,\(len=k+1\) 也有可能合法)
然后我们要接近 \(O(1)\) 判断边长为 \(len\) 的正方形是否合法。考虑哈希。
每个点 \((i,j)\) 的哈希值我们设为 \(a_ib_jc_{i,j}\),这样设方便后续使用乘法分配律。最好使用双模数,这样哈希冲突率是 \(\frac{n^2}{p_1p_2}\),冲突率很小。
用二维前缀和计算出正方形的哈希值的和。然后再计算出我们希望的哈希值,比较它们是否相等。我们希望只有那 \(k\) 行 \(k\) 列的 \(c_{i,j}=1\),其余 \(=0\)。因此我们希望的哈希值就是每一列是 \(b_{j_0}\sum_{i=x_0}^{x_0+len-1} a_i\),一共 \(k\) 列是 \(\sum_{i=x_0}^{x_0+len-1} a_i \sum_{c_{x_1,j}=1} b_j\)。行的同理。然后减去行和列相交的被重复计算的点,即 \(\sum_{c_{i,y_1}=1} a_i \sum_{c_{x_1,j}=1} b_j\)。如果正方形合法,它的哈希值就等于这个了。
这样我们就找到了最小的边长,找最大的边长可以二分,判断是否合法,缩小范围。据说有不带 \(\log\) 的双指针方法还是什么方法,但是本题貌似不卡 \(\log\)。主要是我不会啊
讲完了,感觉不好写,会有很多细节吗?
真是要充分发扬人类智慧才能做出来的题,可惜我没有智慧
虽然我不想打,但是我相信今天不打我明天也不会打的,所以还是今天打吧。结果是今天没打,一直颓