1 条题解

  • 0
    @ 2025-10-29 14:58:29

    题目理解

    我们有一列火车,从站 11 开到站 nn,列车长 Bajtazar 要在途中进行 kk 次查票。
    查票发生在离开某个站点之后,即在区间 (i,i+1)(i, i+1) 进行查票,我们把这个查票位置记为 ii1in11 \le i \le n-1)。

    已知所有乘客的行程信息:xi,jx_{i,j} 表示从站 ii 上车、在站 jj 下车的乘客数量。

    关键规则

    • 如果在某段查票,会检查该段列车上所有乘客的票。
    • 如果某个乘客在之前已经被查过票,那么再次查到时不计入工资。

    目标:选择 kk 个查票位置,使得查到的不重复的乘客数最多。


    思路分析

    1. 乘客被查到的条件

    假设一个乘客从 aa 上车,bb 下车(a<ba < b)。
    这个乘客会在离开站点 a,a+1,,b1a, a+1, \dots, b-1 之后的区间里都在车上。

    如果我们在这 bab-a 个区间中的任何一个查票,都会查到这个乘客。
    只有第一次查到时才算工资

    因此,如果我们选择的查票位置中,该乘客行程覆盖的第一个查票位置是 ppapb1a \le p \le b-1),那么该乘客的票会在位置 pp 被计入。


    2. 问题转化

    我们要选择 kk 个查票位置(1n11 \dots n-1 中选 kk 个),最大化总收益。

    收益计算方式
    对于每个乘客 (a,b)(a,b),如果我们在 [a,b1][a, b-1] 中选择了至少一个查票点,那么该乘客会被计入最小的那个查票点的贡献中。


    3. 动态规划设计

    dp[i][t]dp[i][t] 表示我们考虑了前 ii 个可能的查票位置(即 1i1 \dots i),并且在这里选择了 tt 次查票,所能获得的最大查票数。

    转移方程: [ dp[i][t] = \max_{0 \le j < i} \left( dp[j][t-1] + gain(j, i) \right) ] 其中 gain(j,i)gain(j, i) 表示当上一次查票在位置 jj(若 j=0j=0 表示还没查过票),这次查票在位置 ii 时,新增的乘客数量。


    4. 计算 gain(j, i)

    gain(j,i)gain(j, i) 包含所有满足以下条件的乘客 (a,b)(a,b)

    • ai<ba \le i < b (在位置 ii 查票时乘客在车上)
    • j<aj < a 或者 bj+1b \le j+1
      我们需要仔细分析:乘客 (a,b)(a,b) 在位置 ii 被第一次查到,当且仅当:
      1. ai<ba \le i < b(在位置 ii 时乘客在车上)
      2. [a,i1][a, i-1] 区间内没有查票(否则之前就查到了)

    因为 jj 是上一次查票位置,那么 [j+1,i1][j+1, i-1] 之间没有查票。
    所以如果 aja \le j,那么乘客可能在 jj 或更早被查到过,不算在 gain(j,i)gain(j,i) 中。
    因此条件为:j<ai<bj < a \le i < b

    也就是说,gain(j,i)gain(j,i) = 所有满足 j<ai<bj < a \le i < b 的乘客 (a,b)(a,b) 的数量。


    5. 预处理 gain 数组

    我们可以预处理一个二维数组 g[j][i]g[j][i] 表示 gain(j,i)gain(j,i)

    注意 jj00n1n-1ii11n1n-1,且 j<ij < i

    计算方式:
    固定 jj,对于每个 aa (j+1an1j+1 \le a \le n-1),对于每个 bb (a+1bna+1 \le b \le n),如果 i[a,b1]i \in [a, b-1],那么乘客 (a,b)(a,b) 会对 g[j][i]g[j][i] 贡献 xa,bx_{a,b}

    我们可以用差分数组优化这个预处理,达到 O(n3)O(n^3) 预处理,但 n600n \le 600 可能有点大。不过 k50k \le 50,也许可接受。

    更高效的方法:
    定义 cnt[a][i]cnt[a][i] 表示从 aa 上车,在位置 ii 查票时能查到的乘客数(即 b>ib > ixa,bx_{a,b} 之和)。
    那么: [ g[j][i] = \sum_{a = j+1}^{i} cnt[a][i] ] 其中 cnt[a][i]=b=i+1nxa,bcnt[a][i] = \sum_{b=i+1}^{n} x_{a,b}

    我们可以 O(n2)O(n^2) 预处理 cnt[a][i]cnt[a][i],然后 O(n3)O(n^3) 预处理 g[j][i]g[j][i]
    6003600^3 太大(2.16e8),需要优化。


    6. 优化 gain 计算

    注意到: [ g[j][i] = g[j][i-1] + cnt[i][i] - \sum_{a=j+1}^{i-1} x_{a,i} ] 其中 cnt[i][i]=b=i+1nxi,bcnt[i][i] = \sum_{b=i+1}^n x_{i,b},而 a=j+1i1xa,i\sum_{a=j+1}^{i-1} x_{a,i} 表示那些从 aa (j+1ai1j+1 \le a \le i-1) 上车、在 ii 下车的乘客,他们在位置 ii 查票时已经下车了,所以不算。

    这样我们可以在 O(n2)O(n^2) 时间内预处理 g[j][i]g[j][i]


    7. 动态规划实现

    我们设 dp[i][t]dp[i][t] 表示前 ii 个位置选了 tt 次查票,且最后一次在 ii 查票的最大收益。
    同时用 pre[i][t]pre[i][t] 记录前一个查票位置,用于输出方案。

    转移: [ dp[i][t] = \max_{0 \le j < i} ( dp[j][t-1] + g[j][i] ) ] 初始 dp[0][0]=0dp[0][0] = 0,其他 -\infty

    答案:maxkin1dp[i][k]\max_{k \le i \le n-1} dp[i][k]


    8. 输出方案

    通过 pre[i][t]pre[i][t] 回溯,得到查票位置序列。


    复杂度分析

    • 预处理 cntcntO(n3)O(n^3)(这里可以优化到 O(n2)O(n^2),通过后缀和)
    • 预处理 ggO(n3)O(n^3)(也可以优化到 O(n2)O(n^2)
    • DP:O(n2k)O(n^2 \cdot k)

    由于 n600,k50n \le 600, k \le 50O(n2k)O(n^2 \cdot k)1.8×1071.8 \times 10^7 可接受。


    总结

    这道题的核心在于:

    1. 理解“乘客只在第一次被查时计入”这一规则
    2. 将问题转化为动态规划模型
    3. 高效预处理增益数组 g[j][i]g[j][i]
    4. 通过记录前驱状态输出方案

    这样就能在给定限制内求出最优查票方案。

    • 1

    信息

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