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

130 lines
3.7 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>
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;
}