一、模板
#define lc(p) p << 1 // 左孩子
#define rc(p) p << 1 | 1 // 右孩子
const int MAX = 5e5 + 5; // 数列元素最大个数
ll n, m, w[MAX]; // n -- 数列元素个数; m -- 操作数; w[i] -- 第i个元素的值
struct {int l, r; ll sum, tag;} tree[MAX << 2]; // 一般开元素个数的4倍数组
// 边界为[l, r]; sum -- 区间和; tag -- 懒标记
void pushup(int p)
{
tree[p].sum = tree[lc(p)].sum + tree[rc(p)].sum; // 用区间p的左孩子和右孩子的值更新该区间的值
}
void pushdown(int p)
{
if (tree[p].tag) // 向下传递懒标记
{
tree[lc(p)].sum += (tree[lc(p)].r - tree[lc(p)].l + 1) * tree[p].tag;
tree[lc(p)].tag += tree[p].tag;
tree[rc(p)].sum += (tree[rc(p)].r - tree[rc(p)].l + 1) * tree[p].tag;
tree[rc(p)].tag += tree[p].tag;
tree[p].tag = 0;
}
}
void build(int p, int l, int r)
{
tree[p] = {l, r, w[l], 0};
if (l == r) return;
int m = l + r >> 1; // 递归建立左、右子树
build(lc(p), l, m);
build(rc(p), m + 1, r);
pushup(p);
}
void update(int p, int x, int y, int k)
{
if (x <= tree[p].l && tree[p].r <= y)
{
tree[p].sum += (tree[p].r - tree[p].l + 1) * k;
tree[p].tag += k;
return;
}
pushdown(p);
int m = tree[p].l + tree[p].r >> 1;
if (x <= m) update(lc(p), x, y, k);
if (y > m) update(rc(p), x, y, k);
pushup(p);
}
ll query(int p, int x, int y)
{
if (x <= tree[p].l && tree[p].r <= y)
return tree[p].sum;
pushdown(p);
int m = tree[p].l + tree[p].r >> 1;
ll sum = 0;
if (x <= m) sum += query(lc(p), x, y);
if (y > m) sum += query(rc(p), x, y);
return sum;
}