三十年河东,三十年河西|

自动机

园龄:1年10个月粉丝:2关注:4

Educational Codeforces Round 154 (Rated for Div. 2)

C

题意:

一开始有个空数组,以及一串操作s:
s[i] = +:向空数组末尾中加入一个数
s[i] = -:在数组末尾减去一个数
s[i] = 1:当前数组是递增数组
s[i] = 0:当前数组不是递增数组
问s是否是合法的操作

思路:

非法操作说明当前的 0 和 1 冲突了,当前查询和上一次查询冲突了,因为只关心之前的数组状态,所以令b[len]表示数组长度为len时要求的状态,b[len] = 1表示要求数组长度为len时是递增,b[len] = -1表示要求数组长度为len时是不递增的,b[len] = 0 表示没要求

inline void solve() 
{
    string s; cin >> s;
    std::vector<int> b(s.size() + 1);
    int len = 0;
    bool ans = true;
    b[0] = 1, b[1] = 1; 
    for (int i = 0; i < s.size(); i++)
    {
        if (s[i] == '+')
        {
            if (b[len] == -1) b[len + 1] = -1;
            len++;
        }

        if (s[i] == '-')
        {
            if (b[len] == 1 && len >= 2)
            {
                b[len] = 0;
                b[len - 1] = 1;
            }

            if (b[len] == -1)
            {
                b[len] = 0;
            }

            len--;

            if (len < 0)
            {
                ans = false;
                break;
            }
        }

        if (s[i] == '1')
        {
            if (b[len] == -1)
            {
                ans = false;
                break;
            }
            b[len] = 1;
        }

        if (s[i] == '0')
        {
            if (len < 2)
            {
                ans = false;
                break;
            }

            if (b[len] == 1)
            {
                ans = false;
                break;
            }
            b[len] = -1;
        }
    }

    if (ans) cout << "YES" << endl;
    else cout << "NO" << endl;
}

D

题意:

给定一个数组,每次操作可以选择三个数l, r, x; 让区间[l, r]的数都乘以x,问最少多少次操作可以让数组变成严格单调递增

思路:

因为x可以任意选,所以最终数组中每个数都要么是{负无穷,原数,正无穷}中的一个,定义状态方程为f[i][j]: 让前i个数单调且第i个数的情况为j的最少操作数
f[i][0]: 负无穷, f[i][1]: 原数,f[i][2]: 正无穷
转移方程:先区分a[i]和a[i - 1]的大小,以及当前状态可以由哪些状态转移过来

inline void solve() 
{
    int n; cin >> n;
    std::vector<int> a(n);

    memset(f, 0x3f, sizeof(f));

    for (int i = 0; i < n; i++)
        cin >> a[i];

    f[0][0] = 1; f[0][1] = 0; f[0][2] = 1;

    for (int i = 1; i < n; i++)
    {

        if (a[i] >= a[i - 1]) f[i][0] = f[i - 1][0] + 1; // 负数要反过来,因为大数乘上负数就变小了
        else f[i][0] = f[i - 1][0];

        if (a[i] > a[i - 1])
        {
            f[i][1] = min(f[i - 1][0], f[i - 1][1]);
            f[i][2] = min(min(f[i - 1][0], f[i - 1][1]) + 1, f[i - 1][2]);
        }
        else
        {
            f[i][1] = f[i - 1][0];
            f[i][2] = min(min(f[i - 1][0], f[i - 1][1]), f[i - 1][2]) + 1;
        }
    }

    int ans = inf;
    for (int i = 0; i < 3; i++)
        ans = min(ans, f[n - 1][i]);

    cout << ans << endl;
}

本文作者:自动机

本文链接:https://www.cnblogs.com/monituihuo/articles/17686090.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   自动机  阅读(7)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起