1 条题解

  • 1
    @ 2025-3-8 16:25:34

    考虑枚举最终的颜色 XX

    不难发现,每一段连续的位置只会出现两种情况:

    • 直接被 XX 覆盖。
    • 先被区间最小值覆盖,再被 XX 覆盖。

    对两种情况分别使用区间 DP 即可。

    #include <bits/stdc++.h>
    using namespace std;
    const int P = 1e9 + 7;
    long long d1[312][312], d2[312], d3[312];
    int c[312], cc[312][312], cs[312], f[312];
    int main()
    {
    	int T;
        cin >> T;
        while (T--)
        {
            int n;
            cin >> n;
            long long ans = 0x3f3f3f3f3f3f3f3fll;
            for (int i = 1; i <= n; i++)
            {
                cin >> c[i];
                cs[i] = cs[i - 1] + c[i];
                cc[i][i] = c[i];
                for (int j = 1; j <= i - 1; j++)
                    cc[j][i] = min(cc[j][i - 1], c[i]);
            }
            memset(d1, 0, sizeof d1);
            for (int i = 1; i <= n; i++)
                for (int j = i; j <= n; j++)
                {
                    int mx = 1e9, mc = 0;
                    long long sum = 0;
                    for (int k = i; k <= j; k++)
                    {
                        sum += c[k];
                        if (c[k] < mx) mx = c[k], mc = 0;
                        if (c[k] == mx) mc++;
                    }
                    d1[i][j] = mx * (sum - 1ll * mc * mx);
                }
            for (int i = 1; i <= n; i++)
            {
                memset(d2, 0x3f, sizeof d2);
                memset(d3, 0x3f, sizeof d3);
                memset(f, 0, sizeof f);
                for (int j = 1; j <= n; j++)
                {
                    f[j] = f[j - 1];
                    if (c[i] == c[j]) f[j]++;
                }
                d2[0] = 0;
                for (int j = 0; j <= n - 1; j++)
                {
                    for (int k = j + 1; k <= n; k++)
                    {
                        long long x;
                        x = d2[j] + d1[j + 1][k] + 1ll * cc[j + 1][k] * c[i] * (k - j);
                        d2[k] = min(d2[k], x);
                        x = d3[j] + d1[j + 1][k] + 1ll * cc[j + 1][k] * c[i] * (k - j);
                        d3[k] = min(d3[k], x);
                        if (f[k] == f[j]) continue;
                        x = d2[j] + 1ll * c[i] * (cs[k] - cs[j] - 1ll * c[i] * (f[k] - f[j]));
                        d3[k] = min(d3[k], x);
                        x = d3[j] + 1ll * c[i] * (cs[k] - cs[j] - 1ll * c[i] * (f[k] - f[j]));
                        d3[k] = min(d3[k], x);
                    }
                }
                ans = min(ans, d3[n]);
            }
            cout << ans << endl;
        }
    	return 0;
    }
    

    信息

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