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;
    }
    
  • 相关阅读:
    docker.service启动失败:Unit not found
    本地测试环境搭建
    2016 年总结
    node-http-proxy修改响应结果
    JavaScript那些事儿(01): 对象
    Javascript正则表达式
    addEventListener之handleEvent
    《CSS那些事儿》读书笔记
    《编写高质量代码--Web前端开发修炼之道》读书笔记
    Javascript闭包简单理解
  • 原文地址:https://www.cnblogs.com/mollnn/p/14428390.html
Copyright © 2011-2022 走看看