P1253 扶苏的问题 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
较为模式化的一道题,只不过多了一个覆盖操作,这个操作比较简单,因为如果覆盖了,adder标记就没用了直接清0即可。
使用指针可以避免越界的问题,而且树嘛,总归用指针舒服些
#include<iostream>
#include<algorithm>
using namespace std;
#define MAX (1000010)
#define inf (1e15)
int nums[MAX];
struct Node {
int l, r;
long long value, adder, cover;
Node* left, *right;
//加法打标记时若赋值标记存在则直接给赋值标记加上对应值,不修改加标记,否则修改加标记;打赋值标记时先清空加标记即可。
//覆盖时直接更改value,并将加法标记清0
void change(long long x) {
value = cover = x;
adder = 0;
}
//做加法时,先将值加上,如果存在cover标记,则直接在cover上做加法,因为覆盖过了,adder是没用的
//若没有cover标记,则加法标记增加x
void add(long long x) {
value += x;
if (cover != -inf)
cover += x;//如果被覆盖过,则直接在cover标签上做加法
else
adder += x;//否则在adder上做
}
void Down() {
if (cover != -inf) {
left->change(cover);
right->change(cover);
cover = -inf;
}
else if (adder) {
left->add(adder);
right->add(adder);
adder = 0;
}
}
void Up() {
value = max(left->value, right->value);
}
bool In(int xL, int xR) {
return xL <= l && r <= xR;
}
//注意进行范围判断,否则会越界
bool Out(int xL, int xR) {
return r < xL || xR < l;
}
void update(int L, int R, long long x, int op) {
if (In(L, R)) {
if (op == 1) {
change(x);
}
else if (op == 2) {
add(x);
}
}
else if (!Out(L, R)) {
Down();
left->update(L, R, x, op);
right->update(L, R, x, op);
Up();
}
return;
}
long long query(int L, int R) {
if (In(L, R))
return value;
else if (!Out(L, R)) {
Down();
return max(left->query(L, R), right->query(L, R));
}
else return -inf;
}
};//至此完成线段树节点的定义
Node SegTree[MAX << 1];
Node* p = SegTree;//定义一颗线段树
Node* build(int L, int R) {
Node* q = p++;
q->l = L;
q->r = R;
q->cover = -inf;
q->adder = 0;
if (L != R) {
int mid = L + R >> 1;
q->left = build(L, mid);
q->right = build(mid + 1, R);
q->Up();
}
else q->value = nums[L];
return q;
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);
int n, q;
std::cin >> n >> q;
for (int i = 1; i <= n; ++i) {
std::cin >> nums[i];
}
auto rot = build(1, n);
for (int op, l, r, x; q; --q) {
std::cin >> op >> l >> r;
if (op != 3) {
std::cin >> x;
rot->update(l, r, x, op);
}
else {
std::cout << rot->query(l, r) << std::endl;
}
}
return 0;
}