1 条题解

  • 0
    @ 2026-4-2 23:58:25

    题目详解

    问题重述

    我们有一个 n×mn \times m 的网格,需要放置 ww 只大猩猩(每只大猩猩有身高 aia_i,每个格子最多放一只)。定义观赏值为:所有边长为 kk 的子正方形的观赏值之和,其中每个子正方形的观赏值等于其中所有大猩猩身高之和。

    我们需要最大化这个总观赏值。


    核心思路

    1. 每个格子对总观赏值的贡献次数

    关键观察:
    对于网格中的某个格子 (i,j)(i, j)(这里 i,ji, j00 开始索引),它会被多少个边长为 kk 的子正方形覆盖?

    推导方法

    一个边长为 kk 的子正方形由其左上角 (x,y)(x, y) 唯一确定,其中:

    • 0xnk0 \le x \le n - k
    • 0ymk0 \le y \le m - k

    格子 (i,j)(i, j) 被该子正方形覆盖,当且仅当:

    • xix+k1x \le i \le x + k - 1 \quad\Rightarrow\quad ik+1xii - k + 1 \le x \le i
    • yjy+k1y \le j \le y + k - 1 \quad\Rightarrow\quad jk+1yjj - k + 1 \le y \le j

    同时 xx 必须满足 0xnk0 \le x \le n - kyy 必须满足 0ymk0 \le y \le m - k

    因此 xx 的取值范围是:

    $$x_{\min} = \max(0, i - k + 1), \quad x_{\max} = \min(i, n - k) $$

    yy 的取值范围是:

    $$y_{\min} = \max(0, j - k + 1), \quad y_{\max} = \min(j, m - k) $$

    所以格子 (i,j)(i, j) 被覆盖的次数为:

    $$cnt(i, j) = (\min(i, n - k) - \max(-1, i - k)) \times (\min(j, m - k) - \max(-1, j - k)) $$

    注意:代码中使用 max(-1LL, i - k) 是因为当 ik=1i - k = -1 时,max(1,1)=1\max(-1, -1) = -1,相减后得到 i(1)=i+1i - (-1) = i + 1,等价于 i(ik+1)+1=ki - (i - k + 1) + 1 = k。实际上更清晰的写法是:

    $$cnt(i, j) = (\min(i, n - k) - \max(0, i - k + 1) + 1) \times (\min(j, m - k) - \max(0, j - k + 1) + 1) $$

    但原代码的写法在数学上是等价的。


    2. 贪心策略

    总观赏值可以写成:

    $$\text{总观赏值} = \sum_{\text{每个子正方形}} \sum_{\text{格子在子正方形中}} a_{格子} = \sum_{\text{每个格子}} cnt(i, j) \times a_{格子} $$

    也就是说,每个格子的“重要性”就是它被覆盖的次数 cnt(i,j)cnt(i, j)

    为了最大化总和,我们应该:

    • 将最大的 cnt(i,j)cnt(i, j) 分配给最大的 aa(身高)
    • 将第二大的 cnt(i,j)cnt(i, j) 分配给第二大的 aa
    • 以此类推

    这就是一个典型的贪心策略:大的乘大的,小的乘小的


    3. 算法步骤

    1. 计算每个格子的覆盖次数 cnt(i,j)cnt(i, j),存入数组 prr
    2. 对大猩猩身高数组 arr 从大到小排序。
    3. 对覆盖次数数组 prr 从大到小排序。
    4. 计算 i=0w1prr[i]×arr[i]\sum_{i=0}^{w-1} prr[i] \times arr[i](注意只有前 ww 个格子被放置大猩猩,因为 wn×mw \le n \times m,未被使用的格子贡献为 00)。

    时间复杂度分析

    • 计算所有 n×mn \times m 个格子的覆盖次数:O(nm)O(n \cdot m)
    • 排序 arrO(wlogw)O(w \log w)
    • 排序 prrO(nmlog(nm))O(n \cdot m \log(n \cdot m))
    • 总复杂度:O(nmlog(nm)+wlogw)O(n \cdot m \log(n \cdot m) + w \log w)

    由于所有测试用例的 nmn \cdot m 之和不超过 2×1052 \times 10^5ww 之和也不超过 2×1052 \times 10^5,因此可以在时限内运行。


    代码对应关系

    函数/变量 作用
    calcc(i, j) 计算格子 (i,j)(i, j) 被覆盖的次数 cnt(i,j)cnt(i, j)
    build() 1. 将 arr 降序排序
    2. 遍历所有格子,计算覆盖次数存入 prr
    3. 将 prr 降序排序
    solve() 计算 i=0w1prr[i]×arr[i]\sum_{i=0}^{w-1} prr[i] \times arr[i]

    示例验证(第一个测试用例)

    n=3,m=4,k=2,w=9n = 3, m = 4, k = 2, w = 9
    所有 ai=1a_i = 1,所以任何安排结果相同。

    先计算覆盖次数矩阵(3×43 \times 4):

    手动计算几个:

    • 角上格子 (0,0)(0,0):能被左上角在 (0,0)(0,0)2×22\times 2 子正方形覆盖,只有 11 个 → cnt=1cnt = 1
    • 边中格子 (0,1)(0,1):能被左上角在 (0,0)(0,0)(0,1)(0,1) 的两个子正方形覆盖 → cnt=2cnt = 2
    • 中心格子 (1,1)(1,1):能被左上角在 (0,0),(0,1),(1,0),(1,1)(0,0),(0,1),(1,0),(1,1)44 个子正方形覆盖 → cnt=4cnt = 4

    覆盖次数矩阵:

    1 2 2 1
    2 4 4 2
    1 2 2 1
    

    总观赏值 = 1+2+2+1+2+4+4+2+1+2+2+11+2+2+1+2+4+4+2+1+2+2+1? 不对,需要乘以身高(都是 11)。

    实际上,总观赏值 = 所有覆盖次数之和 = 1+2+2+1+2+4+4+2+1+2+2+1=241+2+2+1+2+4+4+2+1+2+2+1 = 24?但答案是 2121

    这里需要小心:我们只有 w=9w = 9 只大猩猩,不是 1212 个格子。
    所以我们要取覆盖次数最大的 99 个格子:4,4,2,2,2,2,2,2,14,4,2,2,2,2,2,2,1
    排序后:4,4,2,2,2,2,2,2,14,4,2,2,2,2,2,2,1
    和 = 4+4+2+2+2+2+2+2+1=214+4+2+2+2+2+2+2+1 = 21


    注意事项

    1. 使用 long long 存储结果,因为身高最大 10910^9,覆盖次数最大约 k2k^2(但 kmin(n,m)k \le \min(n,m)),乘积可能很大。
    2. 覆盖次数计算时,注意边界条件,尤其是 n=kn = km=km = k 的情况。
    3. 如果 w<nmw < n \cdot m,只使用覆盖次数最大的 ww 个格子,其余格子不放大猩猩。
    • 1

    信息

    ID
    6303
    时间
    1000ms
    内存
    256MiB
    难度
    3
    标签
    递交数
    2
    已通过
    1
    上传者