zoukankan      html  css  js  c++  java
  • [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();
        }
    }
    
  • 相关阅读:
    tarjan——强连通分量+缩点
    题解报告——Financial Crisis
    计算几何刷题计划(转)
    [bzoj1042] [HAOI2008]硬币购物
    [bzoj1584] [Usaco2009 Mar]Cleaning Up 打扫卫生
    bzoj 2783 JLOI2012 树
    bzoj 1150 [CTSC2007]数据备份Backup
    bzoj 1079 [SCOI2008]着色方案
    bzoj 2957 楼房重建
    bzoj 3208 花神的秒题计划I
  • 原文地址:https://www.cnblogs.com/mollnn/p/14461793.html
Copyright © 2011-2022 走看看