线段树

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5; //1~1e5
int sum[maxn << 2]; //用节点维护区间的和
int a[maxn];
int lazy[maxn << 2];

//5~101  5*4=20
//10100 2^4+2^2
//20

void push_up(int rt) {
    sum[rt] = sum[rt << 1] + sum[rt << 1 | 1];
    return;
    //当前节点的信息等于当前节点的左儿子和右儿子的信息之和
}
void push_down(int rt,int mid){
    if(lazy[rt]){
        lazy[rt<<1]+=lazy[rt];
        lazy[rt<<1|1]+=lazy[rt];
        sum[rt<<1]+=lazy[rt]*(mid-(mid>>1));
        sum[rt<<1|1]+=lazy[rt]*mid;
        lazy[rt]=0;
    }    
    return;
}
void build(int l, int r, int rt) {//当前区间是[l,r],当前的根节点是rt
    if(l == r) {
        sum[rt] = 0;
        return;
    }
    int mid = (l + r) >> 1;
    // 除以2
    build(l, mid, rt << 1);
    build(mid + 1, r, rt << 1 | 1); //zou wan le
    push_up(rt); //使得节点rt 得到信息
}

void update(int L, int R, int val, int l, int r, int rt) {
    if(L <= l && r <= R) {
        lazy[rt]+=val; 
        return;
    }
    int mid = (l + r) >> 1;
    push_down(rt,mid);//将节点的lazy标记给递推下去,将加法变成乘法
    if(L <= mid) {
        update(L,R,val, l, mid, rt << 1);
    }
    if(R > mid) {
        update(L,R,val, mid + 1, r, rt << 1 | 1);
    }
    push_up(rt);
}
int query(int L, int R, int l, int r, int rt) { //我需要查询的区间是[L,R],我当前的区间是(l,r),当前的根是rt
    if(L <= l && r <= R) {
        //我递归到的区间在我的所需要查询的区间里面,我就要得到这个递归到的区间的信息
        return sum[rt];
    }
    push_down(rt);
    int ans = 0;
    int mid = (l + r) >> 1;
    if(L <= mid) ans += query(L, R, l, mid, rt << 1);
    if(R > mid) ans += query(L, R, mid + 1, r, rt << 1);
    return ans;
}
int main() {
    int n, q;
    cin >> n >> q;
    for(int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
    }
    build(1, n, 1);
    while(q--) {
        int op, l, r;
        scanf("%d", &op);
        if(op == 1) {
            scanf("%d%d", &l, &r);
            //得到区间l,r的信息
            int ans = query(l, r, 1, n, 1);
        } else {
            int val;
            scanf("%d%d%d", &l, &r,&val);
            update(l, r, val, 1, n, 1);
        }
    }

}
int T[maxn],a[maxn];
void build(int rt,int l,int r){
     if(l == r){
          T[rt] = a[l];
          return;
     }
     int mid = l+r >> 1;
     build(rt<<1,l,mid);
     build(rt<<1|1,mid+1,r);
     T[rt] = max(T[rt<<1],T[rt<<1|1]);
}
void modify(int rt,int l,int r,int pos,int val){
     if(l == r){
          T[rt] = val;
          return;
     }     
     int mid = l+r >> 1;
     if(pos <= mid) modify(rt<<1,l,mid,pos,val);
     else modify(rt<<1|1,mid+1,r,pos,val);
     T[rt] = max(T[rt<<1],T[rt<<1|1]);
}
int query(int rt,int l,int r,int L,int R){
    if(L <= l && r <= R) return T[rt];
    int mid = l+r >> 1;
    if(R <= mid) return query(rt<<1,l,mid,L,R);
    if(L >  mid) return query(rt<<1|1,mid+1,r,L,R);
    return max(query(rt<<1,l,mid,L,R),query(rt<<1|1,mid+1,r,L,R));
}
View Code
原文地址:https://www.cnblogs.com/DWVictor/p/10321710.html