CF1621F Strange Instructions

· · 题解

CF1621F Strange Instructions。

我们有如下贪心策略:

这两个策略已经足够了。记 cur 表示当前收益,ans 表示答案。

注意特判 n = 1 以及全 0 的情况。枚举第一步进行操作 2 还是操作 1 / 3,时间复杂度 \mathcal{O}(n\log n)

const int N = 1e5 + 5;
ll n, a, b, c; char s[N];
int cnt, L, R, one, d[N], e[N];
ll calc(int now) {
    ll p = 1, q = 1, ans = 0, cur = 0;
    cpy(e, d, cnt + 2);
    int tmpL = L, tmpR = R, rest = one;
    while(1) {
        if(now) {
            if(rest == 0) return ans;
            cur += b, rest--;
        } else {
            while(p <= cnt && e[p] == 1) p++;
            if(rest == 0) {
                if(p <= cnt || tmpL > 1 || tmpR > 1) cmax(ans, cur + a);
                if(q < p) rest++, q++, cur -= c;
                else return ans;
            } else {
                if(p <= cnt) e[p]--, cur += a;
                else if(tmpL > 1) tmpL--, cur += a;
                else if(tmpR > 1) tmpR--, cur += a;
                else if(q < p) q++, rest++, cur -= c;
                else if(tmpL) tmpL = 0, cur -= c;
                else if(tmpR) tmpR = 0, cur -= c;
                else return ans;
            }
        } now ^= 1, cmax(ans, cur);
    }
}
void solve() {
    cin >> n >> a >> b >> c >> s + 1;
    cnt = L = R = one = 0;
    for(int i = 1; i <= n; i++) {
        int r = i;
        while(r < n && s[r + 1] == s[i]) r++;
        if(s[i] == '0') {
            if(i == 1) {
                if(r == n) return cout << (n == 1 ? 0 : a) << endl, void();
                L = r - i + 1;
            } else if(r == n) R = r - i + 1;
            else d[++cnt] = r - i + 1;
        } else one += r - i; i = r;
    } sort(d + 1, d + cnt + 1);
    cout << max(calc(0), calc(1)) << endl;
}
int main() {
    int T; cin >> T;
    while(T--) solve();
    return flush(), 0;
}