1 条题解

  • 0
    @ 2026-4-5 17:48:20

    根据标程,对题目 1931C - Make Equal Again 的详细题解如下:


    题意简述

    给定一个长度为 nn 的整数数组 aa,你可以最多一次操作:选择一段连续区间 [i,j][i, j] 和一个值 xx,将该区间内所有元素赋值为 xx,花费为区间长度 ji+1j - i + 1
    问:最少花费多少 burles,能使数组中所有元素相等?


    思路分析

    1. 特殊情况

    如果数组中所有元素已经相等,则不需要任何操作,答案为 00

    2. 一般情况

    因为只能进行一次区间赋值,并且希望花费最小(即区间长度最小),
    我们应当尽可能保留数组两端已经相等的部分,只修改中间一段。


    3. 核心观察

    设:

    • k1k_1 = 数组最长的相等前缀的长度(所有元素都等于 a[0]a[0]
    • k2k_2 = 数组最长的相等后缀的长度(所有元素都等于 a[n1]a[n-1]

    情况 1:a[0]=a[n1]a[0] = a[n-1]

    此时,前缀和后缀的值相同。
    我们可以同时保留前缀和后缀,只修改中间的部分。
    那么:

    • 保留的元素数量 = k1+k2k_1 + k_2
    • 需要修改的元素数量 = n(k1+k2)n - (k_1 + k_2)
    • 答案 = max(0,nk1k2)\max(0, n - k_1 - k_2)

    情况 2:a[0]a[n1]a[0] \neq a[n-1]

    此时,前缀和后缀的值不同。
    我们只能选择保留较长的那一段(因为一次操作只能赋一个值,不能同时保留两端不同的值)。
    那么:

    • 保留的元素数量 = max(k1,k2)\max(k_1, k_2)
    • 需要修改的元素数量 = nmax(k1,k2)n - \max(k_1, k_2)
    • 答案 = max(0,nmax(k1,k2))\max(0, n - \max(k_1, k_2))

    4. 公式总结

    令:

    • k1=最长相等前缀长度k_1 = \text{最长相等前缀长度}
    • k2=最长相等后缀长度k_2 = \text{最长相等后缀长度}

    则:

    $$\text{答案} = \begin{cases} \max(0, n - k_1 - k_2), & \text{if } a[0] = a[n-1] \\[4pt] \max(0, n - \max(k_1, k_2)), & \text{if } a[0] \neq a[n-1] \end{cases} $$

    等价于:

    $$\text{答案} = \max(0, \; n - \big( \text{如果 } a[0]=a[n-1] \text{ 则 } k_1+k_2 \text{ 否则 } \max(k_1, k_2) \big) ) $$

    5. 示例验证

    例:
    [1,2,3,4,5,1][1,2,3,4,5,1]
    k1=1k_1 = 1(只有第一个 11
    k2=1k_2 = 1(只有最后一个 11
    a[0]=a[n1]=1a[0] = a[n-1] = 1
    保留 1+1=21+1=2 个,修改 62=46-2=4

    例:
    [8,8,8,1,2,8,8,8][8,8,8,1,2,8,8,8]
    k1=3k_1 = 3
    k2=3k_2 = 3
    a[0]a[n1]a[0] \neq a[n-1]888 \neq 8?等等,这里 a[0]=8,a[n1]=8a[0]=8, a[n-1]=8,相等)
    等一下,题目示例中第 3 个测试用例:
    8 8 8 1 2 8 8 88\ 8\ 8\ 1\ 2\ 8\ 8\ 8
    a[0]=8,a[n1]=8a[0]=8, a[n-1]=8,相等。
    k1=3,k2=3k_1=3, k_2=3
    保留 3+3=63+3=6,修改 86=28-6=2


    6. 时间复杂度

    • 计算 k1,k2k_1, k_2 各需 O(n)O(n)
    • 总复杂度 O(n)O(n),对每个测试用例独立,满足 nn 总和 2×105\le 2\times 10^5

    7. 代码对应关系

    标程中:

    • i1k1k_1
    • i2k2k_2
    • res 初始为 nn,然后根据条件减去保留的元素数
    • 最后 max(0,res)\max(0, res) 保证非负

    8. 最终答案形式

    对于每个测试用例,输出:

    $$\max\left(0,\; n - \begin{cases} k_1 + k_2, & a[0] = a[n-1] \\ \max(k_1, k_2), & a[0] \neq a[n-1] \end{cases}\right) $$

    其中 k1k_1 为最长相等前缀长度,k2k_2 为最长相等后缀长度。

    #include <iostream>
    #include <vector>
    #include <algorithm>
    
    using namespace std;
    
    void solve() {
        int n;
        cin >> n;
        vector<int> a(n);
        for (int i = 0; i < n; i++) {
            cin >> a[i];
        }
    
        int i1 = 0, i2 = 0;
        while (i1 < n && a[i1] == a[0]) {
            i1++;
        }
        while (i2 < n && a[n - i2 - 1] == a[n - 1]) {
            i2++;
        }
    
        int res = n;
        if (a[0] == a[n - 1]) {
            res -= i1;
            res -= i2;
        } else {
            res -= max(i1, i2);
        }
    
        cout << max(0, res) << endl;
    }
    
    int main() {
        ios::sync_with_stdio(false);
        cin.tie(nullptr);
    
        int t;
        cin >> t;
        while (t--) {
            solve();
        }
    
        return 0;
    }
    
    • 1

    信息

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