#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<algorithm>
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
using namespace std;
const int maxn = 1e5 + 100;
int sto[maxn << 2];
int cover[maxn << 2];
void PushUp(int rt)
{
sto[rt] = max(sto[rt << 1], sto[rt << 1 | 1]);
}
void PushDown(int rt, int cnt) // cnt 表示节点rt下有多少个数
{
if(cover[rt])
{
// 注意这里的更新是将上一次的更新传递给子树。
// 以防止以后更新中用到了子节点
cover[rt << 1] += cover[rt];
cover[rt << 1 | 1] += cover[rt];
// sto 这里,之前没注意,这里更新时应该乘上
// 这个区间包含的数的个数
sto[rt << 1] += (cnt - (cnt >> 1)) * cover[rt];
sto[rt << 1 | 1] += (cnt >> 1) * cover[rt];
cover[rt] = 0;
}
}
void BuildTree(int l, int r, int rt)
{
cover[rt] = 0;
if(l == r)
{
scanf("%d", &sto[rt]);
return;
}
int mid = (l + r) >> 1;
BuildTree(lson);
BuildTree(rson);
PushUp(rt);
}
void update(int L, int R, int v, int l, int r, int rt)
{
if(L <= l && r <= R)
{
// 这里 cover 为什么用 += ,请自己思考.
cover[rt] += v;
sto[rt] += (r - l + 1) * v;
return ;
}
PushDown(rt, r - l + 1);
int mid = (l + r) >> 1;
if(L <= mid) update(L, R, v, lson);
if(mid < R) update(L, R, v, rson);
PushUp(rt);
}
int query(int L, int R, int l, int r, int rt)
{
// 查找的区间包含在当前节点的区间,直接返回当前节点的特征属性
if(L <= l && r <= R) return sto[rt];
PushDown(rt, r - l + 1);
int mid = (l + r) >> 1;
int res = -0x3f3f3f3f;
if(L <= mid) res = max(res, query(L, R, lson));
if(mid < R) res = max(res, query(L, R, rson));
return res;
}
int main()
{
int n, q;
while(scanf("%d%d", &n, &q) != EOF)
{
BuildTree(1, n, 1);
while(q--)
{
char str[5];
scanf("%s", str);
if(str[0] == 'Q')
{
int l, r;
scanf("%d%d", &l, &r);
printf("%d\n", query(l, r, 1, n, 1));
}
else
{
int x, y, value;
scanf("%d%d%d", &x, &y, &value);
update(x, y, value, 1, n, 1);
}
}
}
return 0;
}
线段树区间和最大值
最新推荐文章于 2024-07-04 22:10:47 发布