zoukankan      html  css  js  c++  java
  • [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;
    }
    
  • 相关阅读:
    2016"百度之星"
    codeforces 55 div2 C.Title 模拟
    codeforces 98 div2 C.History 水题
    codeforces 97 div2 C.Replacement 水题
    codeforces 200 div2 C. Rational Resistance 思路题
    bzoj 2226 LCMSum 欧拉函数
    hdu 1163 九余数定理
    51nod 1225 余数的和 数学
    bzoj 2818 gcd 线性欧拉函数
    Codeforces Round #332 (Div. 2)D. Spongebob and Squares 数学
  • 原文地址:https://www.cnblogs.com/mollnn/p/14428390.html
Copyright © 2011-2022 走看看