Files
python/TangDou/AcWing/SegmentTree/P4979_ODT.cpp
HuangHai 1f397eca87 'commit'
2025-08-30 18:35:01 +08:00

97 lines
3.4 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <bits/stdc++.h>
using namespace std;
// 柯朵莉树模板
struct Node {
int l, r, v;
bool operator<(const Node &b) const {
return l < b.l;
}
};
set<Node> s;
set<Node>::iterator split(int x) {
auto it = s.lower_bound({x});
if (it != s.end() && it->l == x) return it;
--it;
int L = it->l, R = it->r, V = it->v;
s.erase(it);
s.insert({L, x - 1, V});
return s.insert({x, R, V}).first;
}
void assign(int l, int r, int v) {
auto R = split(r + 1), L = split(l);
s.erase(L, R);
s.insert({l, r, v});
}
int main() {
#ifndef ONLINE_JUDGE
freopen("P4979.in", "r", stdin);
#endif
// 加快读入
ios::sync_with_stdio(false), cin.tie(0);
int n;
cin >> n; // n个字符,表示材料
int st = 1; // 区间起点start
char x;
cin >> x;
int a = x; // a:当前字符
int b = a; // b:当前的前一个字符
for (int i = 2; i <= n; i++) {
cin >> x;
a = x; // 读入一个字符
if (a != b) { // 如果两个字符不一致,说明开始的新的区间
s.insert({st, i - 1, b}); // 记录上一个区间
st = i; // 记录新的区间起点
}
b = a; // 修改前一个字符
}
s.insert({st, n, a}); // 将尾巴打扫干净
int m; // m次操作
cin >> m;
while (m--) {
cin >> x;
int l, r;
cin >> l >> r;
if (x == 'A') { // 替换材料
char op;
cin >> op;
assign(l, r, op); // 区间平推op
} else { // 询问[l,r]区间内的材料是否合法
auto R = split(r + 1), L = split(l);
/*
此时我们想进行一次推平操作,把[2,8]区间内的元素都改成666.首先我们发现,[8,10]是一个区间,
那么需要先split(9),把[8,8]和[9,10]拆成两个区间。
同理,原来的[1,2]区间,也需要拆成[1,1]和[2,2]。
*/
// 注意:当x=1或y=N时,你的程序不需要判断前后的情况,而只需要判断区间内的情况.
if (l > 1 && r < n) {
// 之所以要判断是不是l>1,是因为下面需要检查前面的区间块,而l=1时,是没有前面的区间块的
// 同理,r < n,是因为r=n时,是没有后面的区间块的
L--; // 前面的区间块,迭代器只能加加减减,有借有还
if (L->v == R->v) { // 如果前面区间的字符与后面区间的字符一样,根据题意,输出NO
puts("No");
continue;
}
L++; // 还原迭代器到原始L区间上,迭代器只能加加减减,有借有还
}
// 检查区间内的值是不是一致,L未能如期到达R,输出NO
auto t = L;
for (; L != R; L++) {
if (L->v != t->v)
break;
}
if (L != R)
puts("No");
else
puts("Yes");
// 检查是同一个区域的进行整理,合并,起到优化作用,不加上会TLE三个点
assign(t->l, (--L)->r, t->v); // --L是最后一个匹配位置,合并[t,--L]
}
}
return 0;
}