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

自动机

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

Educational Codeforces Round 152 (Rated for Div. 2)

C:

题意:

给你一个长度为n的01字符串s,以及q个询问每次询问给出一个区间[l, r],你需要将区间内的字符排序,问q次询问之后可以得到多少个不同的01字符串?

思路:

直接暴力模拟时间复杂度为O(q(r - l)log(r - l))会超时,通过暴力做法可以发现时间主要卡在了排序上,那要怎么样才能简化排序呢?
假设区间[l, r]00010101111,可以直观的发现真正有效的排序区间[l + 3, r - 4],因为头部和尾部已经是有序的了,这启发我们在每次询问的时候都要去找到有效的[l, r]以此来简化排序,那要如何简化呢?
我们可以通过记录每个位置右边的一个1,和左边的第一个0来达到简化效果。

void solve() 
{   
    int n, q; cin >> n >> q;
    string s; cin >> s;
    std::vector<int> last1(n, n); // 右边第一个1
    std::vector<int> last0(n, -1); // 左边第一个0
 
    for(int i = 0;i < n;i++) // 注意边界
    {
        if(i > 0)
        {
            last0[i] = last0[i - 1];
        }
        if(s[i] == '0')
        {
            last0[i] = i;
        }
        if(n - i - 1 < n - 1)
        {
            last1[n - i - 1] = last1[n - i];
        }
        if(s[n - i - 1] == '1')
        {
            last1[n - i - 1] = n - i - 1;
        }
    }
 
    set<PII> ms;
 
    while(q--)
    {
        int l,r;std::cin >> l >> r;
        if(last1[l - 1] > last0[r - 1])
        {
            ms.emplace(-1, -1);
        } else
        {
            ms.emplace(last1[l - 1], last0[r - 1]);
        }
    }
 
    cout << ms.size() << endl;
}

D:

题意:

给你一个只有0, 1, 2组成的数组,你可以进行两种操作:1. 选择一个数花一块钱把它变成红色。 2. 选择一个红色的数让它减一,顺便选左右两个数中的一个也变成红色。
问你最少花多少钱可以把数组全变成红色,初始数组全为蓝色

思路:

对于操作二我们知道,如果2是红色的则可以免费把他的两边都变成红色,是1的话可以让一边变成红色,所以直接贪心先把2都变成红色,把2变成红色之后,这个红色可以一直通过操作二传递到碰到0为止
举个例子:001121100,如果我们先把2变成红色那么子区间0112110都会因为操作二变成红的,代价为一枚金币.

void solve() 
{   
    int n; cin >> n;
    std::vector<int> a(n + 1);
    std::vector<int> st(n + 1);
    for (int i = 1; i <= n; i++) cin >> a[i];

    int ans = 0;
    for (int i = 1; i <= n; i++)
    {
        if (a[i] == 2 && !st[i])
       {    
            ans ++;
            int l = i;
            while (a[l] != 0 && l > 0) st[l] = 1, l--;
            st[l] = 1;
            int r = i;
            while (a[r] != 0 && r <= n) st[r] = 1, r++;
            st[r] = 1;
        }
    }


    for (int i = 1; i <= n; i++)
    {
        if (a[i] == 1 && !st[i])
        {
            ans++;
            bool used = false;
            if (!st[i - 1] && i > 1) st[i - 1] = 1, used = true;
            int r = i;
            while (a[r] != 0 && r <= n) st[r] = 1, r++;
            if (!used) st[r] = 1;
        }
    }

    for (int i = 1; i <= n; i++) if (!st[i]) ans++;
    cout << ans << endl;
}

本文作者:自动机

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

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

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