标签:+= cst col node stream else names struct down
//add,懒标记,给以当前节点为根的子树中的每一个点加上add(不包含根节点) // #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; typedef long long LL; const int N = 100010; int n, m; int w[N]; struct Node { int l, r; //总和 //如果只考虑当前节点及子节点上的标记,当前区间和是多少 ,没考虑所有祖先节点上的标记 LL sum; //懒标记 //给当前区间的所有儿子加上add LL add; }tr[N * 4]; //用子节点的信息来计算父节点的信息 void pushup(int u) { tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum; } void pushdown(int u) { Node &root = tr[u], &left = tr[u << 1], &right = tr[u << 1 | 1]; //如果当前根节点有标记,往下传,还要清空 if (root.add) { left.add += root.add; left.sum += (LL)(left.r - left.l + 1) * root.add; right.add += root.add; right.sum += (LL)(right.r - right.l + 1) * root.add; root.add = 0; } } void build(int u, int l, int r) { if (l == r) tr[u] = {l, r, w[r], 0}; else { tr[u] = {l, r}; int mid = l + r >> 1; build(u << 1, l, mid); build(u << 1 | 1, mid + 1, r); pushup(u); } } void modify(int u, int l, int r, int d) { if (tr[u].l >= l && tr[u].r <= r) { //总和 tr[u].sum += (LL)(tr[u].r - tr[u].l + 1) * d; //懒标记 tr[u].add += d; } // 区间太大,一定要分裂 else { pushdown(u); int mid = tr[u].l + tr[u].r >> 1; if (l <= mid) modify(u << 1, l, r, d); if (r > mid) modify(u << 1 | 1, l, r, d); //当前区间和发生变化,需要向上传 pushup(u); } } LL query(int u, int l, int r) { if (tr[u].l >= l && tr[u].r <= r) return tr[u].sum; //查询子区间 pushdown(u); int mid = tr[u].l + tr[u].r >> 1; LL sum = 0; if (l <= mid) sum = query(u << 1, l, r); if (r > mid) sum += query(u << 1 | 1, l, r); return sum; } int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; i ++ ) scanf("%d", &w[i]); build(1, 1, n); char op[2]; int l, r, d; while (m -- ) { scanf("%s%d%d", op, &l, &r); if (*op == ‘C‘) { scanf("%d", &d); modify(1, l, r, d); } else printf("%lld\n", query(1, l, r)); } return 0; }
A Simple Problem with Integers POJ - 3468 线段树区间修改+区间查询
标签:+= cst col node stream else names struct down
原文地址:https://www.cnblogs.com/QingyuYYYYY/p/12293719.html