You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

97 lines
3.4 KiB

2 years ago
#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;
}