[CF1477B] Nezzar and Binary String

[CF1477B] Nezzar and Binary String - 线段树,时间倒流

Description

两个01串,q个询问,每次询问给定lr,串1lr内所有位置全为0或1,否则NO,询问后可以对lr内严格小于一半区间的字符进行修改,问q次询问过后,串1能否变为串2。

Solution

题目的条件怎么看怎么奇怪,但是时间倒流一下,就顺了

修改->约束->修改->约束->修改->约束->修改->约束->修改->约束->……

并且,每次修改的区间刚好是后面一次约束的区间

由于我们只能修改严格小于一半的元素,所以其实要修改哪些,改成什么,都是固定的

具体地,我们用一个线段树来维护 01 序列,每次修改就是区间覆盖,先查询对应区间 ([l,r]) 内到底是 0 多还是 1 多,哪个多就改成哪个,注意,如果两个一样多,就无解

最后我们还要检查一下搞出来的序列是否等于 A,如果不是,也一样无解

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

#define int long long

struct SegmentTree
{
    vector<int> val;
    vector<int> tag; // 0: no tag, 1: modify to 1, 2: modify to 0
    int n;
    SegmentTree(int n) : n(n)
    {
        val.resize(4 * n + 4);
        tag.resize(4 * n + 4);
    }
    void put(int p, int l, int r, int v)
    {
        val[p] = (r - l + 1) * v;
        tag[p] = 2 - v;
    }
    void pushup(int p)
    {
        tag[p] = 0;
        val[p] = val[p * 2] + val[p * 2 + 1];
    }
    void pushdown(int p, int l, int r)
    {
        if (tag[p])
        {
            int key = 2 - tag[p];
            tag[p] = 0;
            put(p * 2, l, (l + r) / 2, key);
            put(p * 2 + 1, (l + r) / 2 + 1, r, key);
        }
    }
    void build(int p, int l, int r, const vector<int> &src)
    {
        if (l == r)
        {
            put(p, l, r, src[l]);
        }
        else
        {
            build(p * 2, l, (l + r) / 2, src);
            build(p * 2 + 1, (l + r) / 2 + 1, r, src);
            pushup(p);
        }
    }
    void Build(const vector<int> &src) { build(1, 1, n, src); }
    void modify(int p, int l, int r, int ql, int qr, int key)
    {
        if (l > qr || r < ql)
            return;
        if (l >= ql && r <= qr)
        {
            put(p, l, r, key);
        }
        else
        {
            pushdown(p, l, r);
            modify(p * 2, l, (l + r) / 2, ql, qr, key);
            modify(p * 2 + 1, (l + r) / 2 + 1, r, ql, qr, key);
            pushup(p);
        }
    }
    void Modify(int ql, int qr, int key) { modify(1, 1, n, ql, qr, key); }
    int query(int p, int l, int r, int ql, int qr)
    {
        if (l > qr || r < ql)
            return 0;
        if (l >= ql && r <= qr)
        {
            return val[p];
        }
        else
        {
            pushdown(p, l, r);
            return query(p * 2, l, (l + r) / 2, ql, qr) + query(p * 2 + 1, (l + r) / 2 + 1, r, ql, qr);
        }
    }
    int Query(int ql, int qr) { return query(1, 1, n, ql, qr); }
};

void solve()
{
    int n, m;
    cin >> n >> m;
    string str;
    cin >> str;
    vector<int> a(n + 2), b(n + 2);
    for (int i = 1; i <= n; i++)
        a[i] = str[i - 1] == '1';
    cin >> str;
    for (int i = 1; i <= n; i++)
        b[i] = str[i - 1] == '1';
    vector<pair<int, int>> c(m + 2);
    for (int i = 1; i <= m; i++)
    {
        int x, y;
        cin >> x >> y;
        c[i] = {x, y};
    }
    SegmentTree seg(n);
    seg.Build(b);
    for (int i = m; i >= 1; i--)
    {
        auto [l, r] = c[i];
        int len = r - l + 1;
        int c1 = seg.Query(l, r);
        int c0 = len - c1;
        if (c0 == c1)
        {
            cout << "NO" << endl;
            return;
        }
        if (c0 < c1)
        {
            seg.Modify(l, r, 1);
        }
        else
        {
            seg.Modify(l, r, 0);
        }
    }
    for (int i = 1; i <= n; i++)
    {
        if (seg.Query(i, i) != a[i])
        {
            cout << "NO" << endl;
            return;
        }
    }
    cout << "YES" << endl;
}

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

    int t;
    cin >> t;

    while (t--)
    {
        solve();
    }
}
原文地址:https://www.cnblogs.com/mollnn/p/14461793.html