线段树(区间修改)

Posted ak-ls

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了线段树(区间修改)相关的知识,希望对你有一定的参考价值。

#include <iostream>
#include <cctype>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cmath>
#include <vector>
#include <queue>
#include <string>
#include <stack>

using namespace std;

#define ll long long

inline int read() {
    int x = 0,ff = 1; char ch = getchar();
    while(!isdigit(ch)) {
        if(ch == -) ff = -1;
        ch = getchar();
    } 
    while(isdigit(ch)) {
        x = (x << 1) + (x << 3) + (ch ^ 48);
        ch = getchar();
    }
    return x * ff;
}

inline void write(ll x) {
    if(x < 0) putchar(-),x = -x;
    if(x > 9) write(x / 10);
    putchar(x % 10 + 0);
}

const int INF = 0x3f3f3f3f;
const int MAXN = 5e5 + 100;
const int MAXM = 3e3 + 10;

int n,m,a[MAXN];
struct Tree {
    int left,right;
    ll sum,add;
    #define l(x) t[x].left
    #define r(x) t[x].right
    #define sum(x) t[x].sum
    #define add(x) t[x].add
}t[MAXN];

void build(int p,int l,int r) {
    l(p) = l; r(p) = r;
    if(l == r) {sum(p) = a[l]; return ; }
    int mid = (l + r) / 2;
    build(p * 2,l,mid);
    build(p * 2 + 1,mid + 1,r);
    sum(p) = sum(p * 2) + sum(p * 2 + 1);
}

void spread(int p) {
    if(add(p)) {
        sum(p * 2) += add(p) * (r(p * 2) - l(p * 2) + 1);
        sum(p * 2 + 1) += add(p) * (r(p * 2 + 1) - l(p * 2 + 1) + 1);
        add(p * 2) += add(p);
        add(p * 2 + 1) += add(p);
        add(p) = 0;
    }
}

void change(int p,int l,int r,int d) {
    if(l <= l(p) && r >= r(p)) {
        sum(p) += (ll) d * (r(p) - l(p) + 1);
        add(p) += d;
        return ;
    }
    spread(p);
    int mid = (l(p) + r(p)) / 2;
    if(l <= mid) change(p * 2,l,r,d);
    if(r > mid) change(p * 2 + 1,l,r,d);
    sum(p) = sum(p * 2) + sum(p * 2 + 1);
}

ll ask(int p,int l,int r) {
    if(l <= l(p) && r >= r(p)) return sum(p);
    spread(p);
    int mid = (l(p) + r(p)) / 2;
    ll val = 0;
    if(l <= mid) val += ask(p * 2,l,r);
    if(r > mid) val += ask(p * 2 + 1,l,r);
    return val;
}

int main() {
    n = read(); m = read();
    for(int i = 1; i <= n; ++i) a[i] = read();
    build(1,1,n);
    for(int i = 1; i <= m; ++i) {
        char op; int l,r,d;
        cin >> op; l = read(); r = read();
        if(op == C) {
            d = read();
            change(1,l,r,d);
        }
        else {
            write(ask(1,l,r));
            putchar(\n);
        }
    }
    return 0;
}

 

以上是关于线段树(区间修改)的主要内容,如果未能解决你的问题,请参考以下文章

模板线段树-单点修改,区间查询

P3372 模板线段树 1(区间修改区间查询)(树状数组)

线段树区间修改区间求和

线段树 :区间修改,区间查询

数据结构线段树 (定义 & 点修改/区间查询)

HDU - 4578 Transformation(线段树区间修改)