- P63's solution
P63's Solution
- 2025-9-4 21:59:44 @
考虑枚举最终的颜色 。
不难发现,每一段连续的位置只会出现两种情况:
- 直接被 覆盖。
- 先被区间最小值覆盖,再被 覆盖。
对两种情况分别使用区间 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;
}