--- 这里是 cjiaw 的小窝(●'◡'●) ---

正在玩命加载中......

AcWing 243. 一个简单的整数问题2 (线段树 + 懒标记 模板)(树状数组)

题目链接:243. 一个简单的整数问题2 - AcWing题库


题目大意:

给定一个长度为 N 的数列 A,以及 M 条指令,每条指令可能是以下两种之一:

  1. C l r d,表示把 A[l],A[l+1],,A[r] 都加上 d
  2. Q l r,表示询问数列中第 lr 个数的和。

对于每个询问,输出一个整数表示答案。


线段树:

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 200086;
int n, m;
int w[N];

struct node {
    int l, r;
    int s, add;
} e[N << 2];


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

void pushdown(int u) {

    auto &root = e[u], &lf = e[u << 1], &ri = e[u << 1 | 1];
    
    if (root.add) {//懒标记不处理根节点
        lf.add += root.add;
        ri.add += root.add;
        lf.s += (lf.r - lf.l + 1) * root.add;
        ri.s += (ri.r - ri.l + 1) * root.add;
        root.add = 0;
    }
}

void build(int u, int l, int r) {

    if (l == r) e[u] = {l, r, w[l]};
    else {
        e[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 x) {

    if (l <= e[u].l && e[u].r <= r) {
        e[u].add += x;
        e[u].s += (e[u].r - e[u].l + 1) * x;
    } else {
        pushdown(u);
        int mid = (e[u].l + e[u].r) >> 1;
        if (l <= mid) modify(u << 1, l, r, x);
        if (r > mid) modify(u << 1 | 1, l, r, x);
        pushup(u);
    }
    
}

int query(int u, int l, int r) {
    pushdown(u);
    if (l <= e[u].l && e[u].r <= r) return e[u].s;
    else {
        int res = 0;
        int mid = (e[u].l + e[u].r) >> 1;
        if (l <= mid) res = query(u << 1, l, r);
        if (r > mid) res += query(u << 1 | 1, l, r);
        return res;
    }
    
}

signed main() {

    cin >> n >> m;
    for (int i = 1; i <= n; i++) cin >> w[i];
    build(1, 1, n);
    
    while (m--) {
        char c;
        int l, r, x;
        cin >> c >> l >> r;
        if (c == 'Q') cout << query(1, l, r) << endl;
        else {
            cin >> x;
            modify(1, l, r, x);
        }
        
    }
    
    return 0;
}

树状数组:

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 200086;

int n, m;
int w[N];
int d[N], id[N];

int lowbit(int x) {
    return x & -x;
}

void add(int arr[], int i, int x) {
    for (; i <= n; i += lowbit(i)) arr[i] += x;
}

int sum(int arr[], int i) {
    int res = 0;
    for (; i; i -= lowbit(i)) res += arr[i];
    return res;
}

int summ(int u) {
    return sum(d, u) * (u + 1) - sum(id, u);
}

signed main() {

    cin >> n >> m;
    for (int i = 1; i <= n; i++) {
        cin >> w[i];
        int t = w[i] - w[i - 1];
        add(d, i, t);
        add(id, i, i * t);
    }
    
    while (m--) {
        char op;
        int l, r, x;
        cin >> op >> l >> r;
        if (op == 'Q') cout << summ(r) - summ(l - 1) << endl;
        else {
            cin >> x;
            add(d, l, x), add(d, r + 1, -x);
            add(id, l, l * x), add(id, r + 1, (-x) * (r + 1));
        }
    }
    
    return 0;
}

 

posted @ 2025-10-28 17:14  wwjjw  阅读(18)  评论(0)    收藏  举报