1 条题解

  • 0
    @ 2026-5-13 8:10:56

    问题具有显著的阶段性,考虑 DP,设 fif_i 表示前 ii 个人操作后造成的最大伤害。

    首先有直接攻击的转移 fifi1+dbif_i \gets f_{i - 1} + d_{b_i}。在此之外,我们还可以找到一个 (pj,qj,cj)(p_j, q_j, c_j),并且找到一个 k<ik < i,使得 ak=pj,bi=qja_k = p_j, b_i = q_j,转移为 fifk1+cj+dbif_i \gets f_{k - 1} + c_j + d_{b_i}

    考虑记 $s_{q_j} = \{(p_j, c_j)\}, u_{p_j} = \max_{a_k = p_j} \{f_{k - 1}\}$,每次枚举 (pj,cj)sbi(p_j, c_j) \in s_{b_i} 并转移 fiupj+cj+dbif_i \gets u_{p_j} + c_j + d_{b_i} 即可。O(1)\mathcal{O}(1) 维护 upju_{p_j} 是简单的。时间复杂度 O(si+1)\mathcal{O}(|s_i| + 1),可以达到 O(m)\mathcal{O}(m),不能通过。

    我们注意到满足 sqj>B|s_{q_j}| > Bqjq_j 一定不超过 mB\frac{m}{B} 个。考虑仅在 {si}\{s_i\} 中保留 sqjB|s_{q_j}| \leq Bsqjs_{q_j},这时上述转移复杂度降到 O(B)\mathcal{O}(B);而对于剩下的 (pj,qj,cj)(p_j, q_j, c_j)tpj={(qj,cj)}t_{p_j} = \{(q_j, c_j)\},那么一定有 tinB|t_i| \leq \frac{n}{B}

    仅对于在 tpjt_{p_j} 中的 (pj,qj,cj)(p_j, q_j, c_j) 设 $v_{q_j} = \max_{(p_j, q_j, c_j), a_k = p_j} \{f_{k - 1} + c_j\}$,转移时直接 fivbi+dbif_i \gets v_{b_i} + d_{b_i} 即可。维护 vqjv_{q_j} 可以枚举 (qj,cj)tai(q_j, c_j) \in t_{a_i},有 vqjfi1+cjv_{q_j} \gets f_{i - 1} + c_j,时间复杂度 O(ti)=O(mB)\mathcal{O}(|t_i|) = \mathcal{O}(\frac{m}{B})。总时间复杂度 $\mathcal{O}(1 + \frac{m}{B}) = \mathcal{O}(\frac{m}{B})$。

    综上,时间复杂度为 O(n(B+mB))\mathcal{O}(n(B + \frac{m}{B})),显然 B=mB = \sqrt m 时取得最小值 O(nm)\mathcal{O}(n\sqrt m)

    这一方法是一种似乎并不常见的动态规划优化,称为根号分治优化 DP,有较高的思维难度。

    Code:

    #include<bits/stdc++.h>
    #define mem(a, v) memset(a, v, sizeof(a))
    
    using namespace std;
    
    const int maxn = 2e5 + 10, maxm = 2e5 + 10, maxx = 2e5 + 10, maxy = 2e5 + 10, gap = 5e2;
    
    int n, m, x, y;
    int d[maxx], a[maxn], b[maxn], p[maxm], q[maxm], c[maxm], cnt[maxx];
    long long u[maxy], v[maxx], f[maxn];
    vector<pair<int, int> > s[maxx], t[maxy];
    
    int main(){
        scanf("%d %d %d %d", &n, &m, &x, &y);
        for (int i = 1; i <= x; i++){
            scanf("%d", &d[i]);
        }
        for (int i = 1; i <= n; i++){
            scanf("%d %d", &a[i], &b[i]);
        }
        for (int i = 1; i <= m; i++){
            scanf("%d %d %d", &p[i], &q[i], &c[i]);
            cnt[q[i]]++;
        }
        for (int i = 1; i <= m; i++){
            if (cnt[q[i]] > gap){
                t[p[i]].emplace_back(q[i], c[i]);
            }else{
                s[q[i]].emplace_back(p[i], c[i]);
            }
        }
        mem(u, -0x3f), mem(v, -0x3f);
        for (int i = 1; i <= n; i++){
            f[i] = f[i - 1] + d[b[i]];
            if (cnt[b[i]] > gap){
                f[i] = max(f[i], v[b[i]] + d[b[i]]);
            }else{
                for (auto x: s[b[i]]){
                    f[i] = max(f[i], u[x.first] + x.second + d[b[i]]);
                }
            }
            u[a[i]] = max(u[a[i]], f[i - 1]);
            for (auto x: t[a[i]]){
                v[x.first] = max(v[x.first], f[i - 1] + x.second);
            }
        }
        printf("%lld", f[n]);
    
    return 0;
    }
    
    • 1

    信息

    ID
    7426
    时间
    500ms
    内存
    512MiB
    难度
    10
    标签
    递交数
    2
    已通过
    1
    上传者