线段树模板(区间修改,区间查询, 动态开点线段树)

#include <bits/stdc++.h>
using namespace std;

const int N = 1e5 + 5;

int n, m;
int w[N];
struct node {
    int l, r;
    LL sum, add;
}tr[N * 4];

void pushup(int u) {
    tr[u].sum = tr[u << 1].sum + tr[u << 1 | 1].sum;
}

void pushdown(int u) {
    auto &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[l], 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);//pushup
    }
}

void modify(int u, int l, int r, int x) {
    if (tr[u].l >= l && tr[u].r <= r) {
        tr[u].sum += (LL)(tr[u].r - tr[u].l + 1) * x;
        tr[u].add += x;
    }
    else {
        pushdown(u);//modify之间要pushdown
        int mid = tr[u].l + tr[u].r >> 1;
        if (l <= mid) modify(u << 1, l, r, x);
        if (r > mid) modify(u << 1 | 1, l, r, x);
        pushup(u);//注意pushup
    }
}

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 ans = 0;
    if (l <= mid) ans = query(u << 1, l, r);
    if (r > mid) ans += query(u << 1 | 1, l, r);
    return ans;
}

int main() {
    cin >> n >> m;
    for (int i = 1; i <= n; i ++) cin >> w[i];

    build(1, 1, n);

    while (m --) {
        char op; cin >> op;
        int l, r, x;
        cin >> l >> r;

        if (op == 'Q') cout << query(1, l, r) << endl;
        else {
            cin >> x;
            modify(1, l, r, x);
        }
    }
    return 0;
}

 

 

动态开点线段树不再具有left = u << 1, right = u << 1 | 1的性质,但是不需要离散化就可以处理大范围的数,包括负数

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int N = 1e5 + 5;
 5 
 6 int n, m, nidx;
 7 int w[N];
 8 struct node {
 9     int l, r;
10     LL sum, add;
11 }tr[N << 6];
12 
13 void pushup(int u) {
14     tr[u].sum = tr[tr[u].l].sum + tr[tr[u].r].sum;
15 }
16 
17 void pushdown(int u, int l, int r) {
18     if (!tr[u].l) tr[u].l = ++ nidx;
19     if (!tr[u].r) tr[u].r = ++ nidx;
20 
21     auto &root = tr[u], &left = tr[tr[u].l], &right = tr[tr[u].r];
22     int mid = l + r >> 1;
23     if (root.add) {
24         left.add += root.add, left.sum += (LL)(mid - l + 1) * root.add;
25         right.add += root.add, right.sum += (LL)(r - mid) * root.add;
26         root.add = 0;
27     }
28 }
29 
30 void modify(int u, int l, int r, int ll, int rr, int x) {
31     if (l >= ll && r <= rr) {
32         int len = r - l + 1;
33         tr[u].sum += (LL)len * x;
34         tr[u].add += x;
35     }
36     else {
37         pushdown(u, l, r);//modify之间要pushdown
38         int mid = l + r >> 1;
39         if (ll <= mid) modify(tr[u].l, l, mid, ll, rr, x);
40         if (rr > mid) modify(tr[u].r, mid + 1, r, ll, rr, x);
41         pushup(u);//注意pushup
42     }
43 }
44 
45 LL query(int u, int l, int r, int ll, int rr) {
46     if (l >= ll && r <= rr) return tr[u].sum;
47     if (l > rr || r < ll) return 0;
48 
49     pushdown(u, l, r);
50     int mid = l + r >> 1;
51     LL ans = 0;
52     if (l <= mid) ans = query(tr[u].l, l, mid, ll, rr);
53     if (r > mid) ans += query(tr[u].r, mid + 1, r, ll, rr);
54     return ans;
55 }
56 
57 int main() {
58 
59     cin >> n >> m;
60     for (int i = 1; i <= n; i ++) cin >> w[i], modify(1, -INF, INF, i, i, w[i]);
61 
62     while (m --) {
63         char op; cin >> op;
64         int l, r, x;
65         cin >> l >> r;
66 
67         if (op == 'Q') cout << query(1, -INF, INF, l, r) << endl;
68         else {
69             cin >> x;
70             modify(1, -INF, INF, l, r, x);
71         }
72     }
73     return 0;
74 }

 

posted @ 2022-10-13 20:46  Leocsse  阅读(120)  评论(0)    收藏  举报