1 条题解

  • 0
    @ 2026-5-5 13:27:18

    题意简述

    有一个长度为 nn 的土豆焗菜被切成 kk 块,长度分别为 aia_i。每次操作可将一块长度 2\ge 2 的块分成 11ai1a_i-1,或将一块(任意长度)与一块长度为 11 的块合并。求将所有块合并成完整一段所需的最少操作次数。

    核心观察

    • 长度为 11 的块是合并的关键:任何长度大于 11 的块只能通过与长度为 11 的块合并来增长。
    • 因此我们可以选择一块作为“主段”(不切割它),将其他所有块都变成 11 并用主段逐一合并。
    • 处理一块长度为 LL 的块(非主段)需要:
      • 切割 L1L-1 次,将其变成 LL11
      • 合并 LL 次,将每个 11 与主段合并。
    • 总操作次数为 (L1)+L=2L1(L-1) + L = 2L - 1。特殊地,如果该块原长就是 11,只需合并 11 次,即 2×11=12\times1 - 1 = 1

    公式推导

    设我们选择长度为 xx 的块作为主段,其余块的总长度为 nxn - x,共有 k1k-1 块。

    总操作次数 = $\sum_{\text{其他块}} (2a_i - 1) = 2(n - x) - (k - 1) = 2n - 2x - k + 1$。

    为了使操作次数最少,需要让 xx 尽可能大,即选择最长的一块作为主段

    答案为:

    ans=2n2max(a)k+1\text{ans} = 2n - 2\max(a) - k + 1

    时间复杂度 O(k)O(k) 每组,总 O(k)2×105O(\sum k) \le 2\times 10^5

    参考代码

    #include <bits/stdc++.h>
    using namespace std;
    using ll = long long;
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
    
        int t;
        cin >> t;
        while (t--) {
            int n, k;
            cin >> n >> k;
            vector<int> a(k);
            int mx = 0;
            for (int i = 0; i < k; ++i) {
                cin >> a[i];
                mx = max(mx, a[i]);
            }
            ll ans = 2LL * n - 2LL * mx - k + 1;
            cout << ans << "\n";
        }
        return 0;
    }
    
    • 1

    信息

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