[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();
}
}