#牛客春招刷题训练营# + 链接

假定染色后的气球形如 xxxyyyzzz ,三个区间的右端点分别为i,j,n

用 s(x,i) 表示前i个气球中所有原本是x色的染色费用和

则有 cost=(s(y,i)+s(z,i))+((s(x,j)-s(x,i))+(s(z,j)-s(z,i)))+((s(x,n)-s(x,j))+(s(y,n)-s(y,j)))

简化可得 cost=s(x,n)+s(y,n)+(s(y,i)-s(x,i))+(s(z,j)-s(y,j))

因此可以再维护(s(y,i)-s(x,i))的前缀最小值,使复杂度降为O(n)

显然,xyz的枚举可以直接调用全排列函数

最后,再通过设置i跟0可重合、j跟i可重合,可以覆盖最终单色或双色的方案。

#include <algorithm>
#include <bits/stdc++.h>
using namespace std;

using ll = long long;
const int MAXN=200010;
char a[MAXN];
int t[MAXN];
ll s[3][MAXN], mn[MAXN];

int main() {
    int n;
    scanf("%d", &n);
    scanf("%s", a+1);
    for (int i=1;i<=n;i++) {
        scanf("%d", t+i);
    }
    for (int i=1;i<=n;i++) {
        for (int j=0;j<3;j++) s[j][i] = s[j][i-1];
        s[a[i]-'0'][i] += t[i];
    }
    int x[3]={0,1,2};
    ll ans = 1LL<<60;
    do {
        ll ff = s[x[0]][n]+ s[x[1]][n];
        mn[0] = 0;
        for (int i=1;i<=n;i++) {
            mn[i] = min(mn[i-1], s[x[1]][i]-s[x[0]][i]);
        }
        for (int j=0;j<=n;j++) {
            ll res = ff+s[x[2]][j]-s[x[1]][j]+mn[j];
            ans = min(ans, res);
        }
    } while (next_permutation(x, x+3));
    printf("%lld\n", ans);
    return 0;
}