[CF1411D] Grime Zoo

[CF1411D] Grime Zoo - 贪心,组合

Description

给定由字符 0,1,? 组成的字符串 s 和参数 x,y,需要在所有字符为 ? 的位置填入 0 或者 1。这个字符串的价值为子序列 01 的数量乘以 x 加上 10 的数量乘以 y。求字符串价值的最小值。

Solution

存在一个分割点,分割点之前的 ? 全部填一个值,后面的全部填另一个值

在 x>y 时,我们希望多点 10,所以前面的 ? 填 1,后面的 ? 填 0,反过来同理

现在我们去枚举分割点,关键是怎样计算答案

假设分割点为 i

考虑前 0 后 1 的情况

额外的 01 个数,等于前面的 0 的个数乘以后面的 ? 个数,加上前面的 ? 个数乘以后面的 1 个数

考虑前 1 后 0 的情况

额外的 10 个数,等于前面的 1 的个数乘以后面的 ? 个数,加上前面的 ? 个数乘以后面的 0 个数

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

#define int long long

signed main()
{
    ios::sync_with_stdio(false);

    string str;
    int x, y;
    cin >> str >> x >> y;
    int n = str.length();

    int c01 = 0, c10 = 0;
    int c0 = 0, c1 = 0;

    vector<int> a0(n + 2), a1(n + 2), b(n + 2), a(n + 2);
    for (int i = 1; i <= n; i++)
    {
        a0[i] = str[i - 1] == '0';
        a1[i] = str[i - 1] == '1';
        b[i] = str[i - 1] == '?';
        a0[i] += a0[i - 1];
        a1[i] += a1[i - 1];
        b[i] += b[i - 1];
        if (str[i - 1] == '0')
            c0++;
        if (str[i - 1] == '1')
            c1++;
        if (str[i - 1] == '1')
            c01 += c0;
        if (str[i - 1] == '0')
            c10 += c1;
    }

    auto f0 = [&](int l, int r) -> int { return a0[r] - a0[l - 1]; };
    auto f1 = [&](int l, int r) -> int { return a1[r] - a1[l - 1]; };
    auto fb = [&](int l, int r) -> int { return b[r] - b[l - 1]; };

    int tans = 0;

    int ans = 1e18;

    for (int i = 1; i <= n; i++)
    {
        if (str[i - 1] == '0' || str[i - 1] == '?')
            a[i] = 0, tans += y * f1(1, i - 1);
        else
            a[i] = 1, tans += x * (f0(1, i - 1) + fb(1, i - 1));
    }

    ans = min(ans, tans);
    for (int i = 1; i <= n; i++)
        if (str[i - 1] == '?')
        {
            a[i] = 1;
            tans -= y * (f1(1, i - 1) + fb(1, i - 1)) + x * (f1(i + 1, n));
            tans += x * (f0(1, i - 1)) + y * (f0(i + 1, n) + fb(i + 1, n));
            ans = min(ans, tans);
        }

    tans = 0;

    for (int i = 1; i <= n; i++)
    {
        if (str[i - 1] == '0')
            a[i] = 0, tans += y * (f1(1, i - 1) + fb(1, i - 1));
        else
            a[i] = 1, tans += x * (f0(1, i - 1));
    }
    ans = min(ans, tans);

    for (int i = 1; i <= n; i++)
        if (str[i - 1] == '?')
        {
            a[i] = 0;
            tans -= x * (f0(1, i - 1) + fb(1, i - 1)) + y * (f0(i + 1, n));
            tans += y * (f1(1, i - 1)) + x * (f1(i + 1, n) + fb(i + 1, n));
            ans = min(ans, tans);
        }

    cout << ans << endl;
}
原文地址:https://www.cnblogs.com/mollnn/p/14428390.html