Files
python/TangDou/AcWing/SegmentTree/P4979_XKS.cpp

130 lines
3.7 KiB
C++
Raw Normal View History

2025-08-30 18:35:01 +08:00
#include <bits/stdc++.h>
const int N = 1000010;
using namespace std;
// 线段树模板
#define int long long
#define ls (u << 1)
#define rs (u << 1 | 1)
#define mid ((l + r) >> 1)
struct Node {
int l, r, len;
int sum, tag;
} tr[N];
int a[N];
int n, m;
void pushup(int u) {
tr[u].sum = tr[ls].sum + tr[rs].sum;
}
void build(int u, int l, int r) {
tr[u].l = l, tr[u].r = r, tr[u].len = r - l + 1;
if (l == r) {
tr[u].sum = a[l]; // 初始化线段树
return;
}
build(ls, l, mid);
build(rs, mid + 1, r);
pushup(u);
}
// 向下推送懒标记
void pushdown(int u) {
if (tr[u].tag) {
tr[ls].tag = tr[rs].tag = tr[u].tag;
tr[ls].sum = tr[ls].len * tr[u].tag;
tr[rs].sum = tr[rs].len * tr[u].tag;
tr[u].tag = 0; // 向下传递懒标记完毕,将父节点的懒标记修改为0
}
}
// 整体区间赋值为v
void modify(int u, int L, int R, int v) { // 整体区间赋值为v
int l = tr[u].l, r = tr[u].r;
if (l > R || r < L) return;
if (l >= L && r <= R) {
tr[u].sum = tr[u].len * v; // sum和=区间长度*v
tr[u].tag = v; // 懒标记=v
return; // 不再继续向下传递
}
pushdown(u); // 如果存在懒标记,在分裂前就下传懒标记
modify(ls, L, R, v), modify(rs, L, R, v);
pushup(u);
}
// 区间查询
int query(int u, int L, int R) {
int l = tr[u].l, r = tr[u].r;
if (l > R || r < L) return 0;
if (l >= L && r <= R) return tr[u].sum;
pushdown(u);
return query(rs, L, R) + query(ls, L, R);
}
// 将字符映射成数字
int get(char op) {
if (op == 'A') return op * 1234;
if (op == 'B') return op * 12345;
if (op == 'C') return op * 123456;
}
/*[l,r]之间是不是全是A、B、C?
方法:整数HASH(我给起的名字)
步骤:1、A=1234 B=12345 C=123456
2、如果区间内全是A,则区间长度(r-l+1)*1234=sum
3、如果区间内全是B,则区间长度(r-l+1)*12345=sum
4、如果区间内全是C,则区间长度(r-l+1)*123456=sum
*/
bool check(int sum, char c, int l, int r) {
if (c == 'A') return sum == c * 1234 * (r - l + 1);
if (c == 'B') return sum == c * 12345 * (r - l + 1);
if (c == 'C') return sum == c * 123456 * (r - l + 1);
}
signed main() {
#ifndef ONLINE_JUDGE
freopen("P4979.in", "r", stdin);
#endif
// 加快读入
ios::sync_with_stdio(false), cin.tie(0);
cin >> n;
for (int i = 1; i <= n; i++) {
char op;
cin >> op;
a[i] = get(op);
}
build(1, 1, n);
int l, r;
cin >> m;
while (m--) {
char op;
cin >> op;
if (op == 'A') { // 区间替换操作
char x;
cin >> l >> r;
cin >> x; // 替换成啥
modify(1, l, r, get(x));
} else {
cin >> l >> r;
int sum = query(1, l, r);
// 区间内是不是都是一样的字符
if ((!check(sum, 'A', l, r) && !check(sum, 'B', l, r) && !check(sum, 'C', l, r))) {
puts("No");
continue;
}
// l=1时,没有前面的内容;r=n时,没有后面的内容,这两种情况,不需要检查是不是前后一致,只需要检查区间内是不是都是一样的即可
if (l == 1 || r == n) {
puts("Yes");
continue;
}
// 执行到这里,肯定是区间内都是一样的,并且,l>1 && r<n
if (query(1, l - 1, l - 1) != query(1, r + 1, r + 1))
puts("Yes");
else
puts("No");
}
}
return 0;
}