线段树 -- 递归 -- 结构体写法模板

版权声明:本博客版权属于BIGBIGPPT,未经允许不得商用 https://blog.csdn.net/BIGBIGPPT/article/details/88913813
#include<bits/stdc++.h>

using namespace std;

int n,p,a,b,m,x,y,ans;

struct node
{
    int l,r,w,f;
}tree[400001];

inline void build(int k, int ll, int rr){//建树 
    tree[k].l = ll, tree[k].r = rr;
    if(tree[k].l == tree[k].r){
        scanf("%d", &tree[k].w);
        return;
    }
    int m = (ll + rr) / 2;
    build(k * 2, ll, m);
    build(k * 2 + 1, m + 1, rr);
    tree[k].w = tree[k * 2].w + tree[k * 2 + 1].w;
}

inline void down(int k){//标记下传 
    tree[k*2].f+=tree[k].f;
    tree[k*2+1].f+=tree[k].f;
    tree[k*2].w+=tree[k].f*(tree[k*2].r-tree[k*2].l+1);
    tree[k*2+1].w+=tree[k].f*(tree[k*2+1].r-tree[k*2+1].l+1);
    tree[k].f=0;
}

inline void ask_point(int k){//单点查询
    if(tree[k].l == tree[k].r){
        ans=tree[k].w;
        return ;
    }
    if(tree[k].f) down(k);
    int m = (tree[k].l + tree[k].r) / 2;
    if(x <= m) ask_point(k * 2);
    else ask_point(k * 2 + 1);
}

inline void change_point(int k){//单点修改 
    if(tree[k].l == tree[k].r){
        tree[k].w += y;
        return ;
    }
    if(tree[k].f) down(k);
    int m = (tree[k].l + tree[k].r) / 2;
    if(x <= m) change_point(k * 2);
    else change_point(k * 2 + 1);
    tree[k].w = tree[k*2].w + tree[k * 2 + 1].w; 
}

inline void ask_interval(int k){//区间查询
    if(tree[k].l >= a && tree[k].r <= b){
        ans += tree[k].w;
        return ;
    }
    if(tree[k].f) down(k);
    int m = (tree[k].l+tree[k].r) / 2;
    if(a <= m) ask_interval(k * 2);
    if(b > m) ask_interval(k * 2 + 1);
}

inline void change_interval(int k){//区间修改
    if(tree[k].l >= a && tree[k].r <= b){
        tree[k].w += (tree[k].r - tree[k].l + 1) * y;
        tree[k].f += y;
        return ;
    }
    if(tree[k].f) down(k);
    int m = (tree[k].l + tree[k].r) / 2;
    if(a <= m) change_interval(k * 2);
    if(b > m) change_interval(k * 2 + 1);
    tree[k].w = tree[k * 2].w + tree[k * 2 + 1].w;
}

int main()
{
    scanf("%d%d", &n, &m);//n个节点m种操作 
    build(1, 1, n);//建树 
    for(int i = 1; i <= m; ++i){
        scanf("%d", &p);
        ans = 0;
        if(p == 1){
            scanf("%d", &x);
            ask_point(1);//单点查询,输出第x个数 
            printf("%d", ans);
        }
        else if(p == 2){
            scanf("%d%d", &x, &y);
            change_point(1);//单点修改 
        }
        else if(p == 3){
            scanf("%d%d", &a, &b);//区间查询 
            ask_interval(1);
            printf("%d\n", ans);
        }
        else{
             scanf("%d%d%d", &a, &b, &y);//区间修改 
             change_interval(1);
        }
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/BIGBIGPPT/article/details/88913813