题目大意:
给一个数组,给定q次操作,每次操作包含以下三种情况:
先输入op,l,r,若op!=3,则输入x.
- 若 op=1,则接下来有三个整数 𝑙,𝑟,𝑥,表示将区间 [𝑙,𝑟]内的每个数都修改为 𝑥。
- 若 op=2,则接下来有三个整数 𝑙,𝑟,𝑥,表示将区间 [𝑙,𝑟] 内的每个数都加上 𝑥。
- 若 op=3,则接下来有两个整数 𝑙,𝑟,表示查询区间 [𝑙,𝑟] 内的最大值。
这问题很简单,只不过写长代码的时候需要稍微注意一下,不要写错了,我就是因为写错了两个字母,导致这题找bug找了两个小时。
首先可以知道,如果给区间先重置为a,后加b,则该区间数全部会变为最后"a+b",也就是之前的标记全部忽略不计,若先加a,后重置b,则全部变成b,优先级毋庸置疑是重置的优先级高,所以下发懒信息的时候需要先下发重置信息,并且将之前累加的懒信息清零。
如:
void laze(ll i, ll pl, ll pr, ll add, ll rev) {//add是累加信息,rev是重置信息
if (rev != inf) {
tagg[i] = rev;
tag[i] = 0;
tree[i] = rev;
}
if (add != inf) {
tag[i] += add;
tree[i] += add;
}
}
接下来直接看代码,有不清楚的欢迎评论区讨论或者私信我:
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const ll N = 1e6 + 5;
const ll inf = 1e18;
//tag为累加add懒信息,tagg为rev重置懒信息
ll tree[N << 2], tag[N << 2], tagg[N << 2];
ll a[N];
int lson(int i) {//访问左儿子
return i << 1;
}
int rson(int i) {//访问右儿子
return i << 1 | 1;
}
void up(ll i) {//求当前节点最大值
tree[i] = max(tree[lson(i)], tree[rson(i)]);
}
void laze(ll i, ll pl, ll pr, ll add, ll rev) {
if (rev != inf) {//优先级rev比较大,必须先判断rev
tagg[i] = rev;
tag[i] = 0;//重置后累加懒信息应该清零
tree[i] = rev;
}
if (add != inf) {
tag[i] += add;
tree[i] += add;
}
}
void down(ll i, ll pl, ll pr) {
if (tag[i] || tagg[i] != inf) {//如果由任意一个懒信息,都要下发
ll mid = (pl + pr) >> 1;
laze(lson(i), pl, mid, tag[i], tagg[i]);
laze(rson(i), mid + 1, pr, tag[i], tagg[i]);
tag[i] = 0;
tagg[i] = inf;
}
}
void build(ll i, ll pl, ll pr) {//建树
tag[i] = 0;
tagg[i] = inf;//先初始化懒信息
if (pl == pr) {
tree[i] = a[pl];
return ;
}
ll mid = (pl + pr) >> 1;
build(lson(i), pl, mid);
build(rson(i), mid + 1, pr);
up(i);
}
void updata(ll i, ll pl, ll pr, ll L, ll R, ll add, ll rev) {
if (L <= pl && pr <= R) {
laze(i, pl, pr, add, rev);
return ;
}
//需要先下发懒信息,使得子树信息正确
down(i, pl, pr);
ll mid = (pl + pr) >> 1;
if (L <= mid) {
updata(lson(i), pl, mid, L, R, add, rev);
}
if (R > mid) {
updata(rson(i), mid + 1, pr, L, R, add, rev);
}
up(i);
}
ll query(ll i, ll pl, ll pr, ll L, ll R) {
if (L <= pl && pr <= R) {
return tree[i];
}
//同样需要先下发懒信息
down(i, pl, pr);
ll mid = (pl + pr) >> 1;
ll maxx = -inf;
if (L <= mid) {
maxx = max(maxx, query(lson(i), pl, mid, L, R));
}
if (R > mid) {
maxx = max(maxx, query(rson(i), mid + 1, pr, L, R));
}
return maxx;
}
int main() {
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int n, q;
cin >> n >> q;
for (int i = 1; i <= n; i++)cin >> a[i];
build(1, 1, n);//建树
while (q--) {
ll op, l, r, x;
cin >> op >> l >> r;
if (op == 1) {
cin >> x;
updata(1, 1, n, l, r, inf, x);//传入add值为inf,方便laze函数特判
} else if (op == 2) {
cin >> x;
updata(1, 1, n, l, r, x, inf);//传入rev值为inf,方便laze函数特判
} else {
cout << query(1, 1, n, l, r) << '\n';
}
}
return 0;
}
今天学习到此结束,大家下次再见吖。