Cover the Grid 题解
简要题意
给出一个 \(n\times n\) 的网格,其中 \(m\) 个格子被染黑。以网格左下角为原点,底边为 \(x\) 轴,左边为 \(y\) 轴,向右、向上为正方向,建立平面直角坐标系。每次可以选择网格下底边的一段区间 \([l,r]\) ( \(0\leq l<r\leq n\) ),盖住以线段 \((l,0),(r,0)\) 为底边,第一象限内的等腰直角三角形,并花费 \(r-l\) 的代价。
对于 \(k=1,2,\dots,n\) ,求在代价总和不超过 \(k\) 的情况下,最终所能覆盖的黑色面积最大值 \(S_k\) 。为了方便,依次输出 \(4S_1,4S_2,\dots,4S_n\)。
题解
我们记 \(T_{l,r}\) 为以线段 \((l,0),(r,0)\) 为底边,第一象限内的等腰直角三角形,\(t_{l,r}\) 为 \(T_{l,r}\) 所盖住的黑色部分面积。
首先说明一个简单的小结论:我们不会选出重叠的两个三角形。因为如果我们选择了\(T_{a,b},T_{c,d}\) 且 \(a\leq c\leq b\leq d\),我们耗费了 \((b-a)+(d-c)\) 的代价。而如果将两个三角形替换为 \(T_{a,d}\) ,那么代价变为 \(d-a\leq (b-a)+(d-c)\) ,同时 \(T_{a,d}\) 完全覆盖了 \(T_{a,b}\) 和 \(T_{c,d}\) ,所以选择重叠的三角形必然不优。
那么就不难得到一个时间复杂度为 \(O(n^3)\) 的 \(\mathrm {dp}\) 做法:设 \(f_{i,j}\) 为当前所选的三角形右顶点不超过 \(i\) ,总代价为 \(j\) 覆盖的最大黑色面积,那么转移为:
我们发现,\(i-j=(i-l)-(j-l)\) ,这说明我们可以将 \(i-j\) 相同的 \(f_{i,j}\) 分别独立计算。
从小到大枚举 \(d=i-j\) ,记 \(g_i=f_{i+d,i}\) ,其中 \(i=1,2,\dots,n-d\) 。将 \(g_i\) 初值设为 \(f_{i+d-1,i}\) 后,就可以将原问题转化为 \(n\) 个(也有可能是 \(n-1\) 个)独立的动态规划问题,并将 \(d\) 看作常数。状态转移方程:
经过一番挖掘,我们可以发现一个优秀的性质:对于 \(i<j<k<l\) ,若 \(g_i+t_{i+d,k+d}\geq g_j+t_{j+d,k+d}\) ,则 \(g_i+t_{i+d,l+d}\geq g_j+t_{j+d,l+d}\) ,换句话说,如果 从 \(i\) 转移到 \(k\) 比从 \(j\) 转移到 \(k\) 更优,那么对于 \(k\) 之后的每个 \(l\) ,从 \(i\) 转移到 \(l\) 也比从 \(j\) 转移到 \(l\) 更优。原因也很浅显:\(T_{i+d,l+d}\setminus T_{i+d,k+d}\) (这两个三角形的“差”)完全地覆盖了 \(T_{j+d,l+d}\setminus T_{j+d,k+d}\) 。
这样,我们得到了一个类似决策单调性的性质,那么也尝试用类似处理决策单调性的方式优化它。
在我们遍历 \(i\) 来计算 \(g\) 的同时,我们维护一个栈 \(st\),栈中每个元素有两个属性 \((x,r)\),分别表示所记录决策点 \(x\),以及 \(x\) 可能影响到的最远位置 \(r\),记栈顶元素为 \(tp\)。每次我们遍历到 \(i\) 时,依次进行以下操作:
- 当 \(tp.r<i\) 时,说明 \(tp.x\) 对于 \(g_i\) 必然不优,将栈顶弹出,直到 \(tp.r\geq i\) 或栈为空。
- 此时,由我们维护的栈的意义,直接由 \(g_{tp.x}\) 转移到 \(g_i\)。
- 接下来,我们要将 \(i\) 加入栈中。首先,对于 \(i,tp.x\),二分出一个位置 \(p\),使得由 \(i\) 转移到 \(p\) 优于 由 \(tp.x\) 转移到 \(p\)(即 \(g_i+t_{i+d,p+d}>g_{tp.x}+t_{tp.x+d,p+d}\) ),同时由 \(i\) 转移到 \(p+1\) 不优于 由 \(tp.x\) 转移到 \(p+1\)。因为我们之前得到的性质,这说明对于 \(i+1,i+2,\dots,p\) 内的 \(j\),由 \(i\) 转移到 \(j\) 比由 \(tp.x\) 转移到 \(j\) 更好,而且 \(p+1\) 之后的 \(j\) 相反。此时如果有 \(p\geq tp.r\),说明 \(tp\) 再无用武之地,所以弹出栈顶。
- 重复 \(3\) 之中的过程,直到此时栈为空或栈顶 \(tp\) 满足 \(tp.r>p\)。这时,我们就可以将 \((i,p)\) 加入栈中,并保持栈内单调性。
这样,对于每个 \(d\),我们可以以 \(O(n\log n)\) 的时间复杂度计算出对应的 \(g\)。
总时间复杂度 \(O(n^2\log n)\)

浙公网安备 33010602011771号