线段树模板

线段树模板

HDU - 1166 - 敌兵布阵

本题为单点修改+区间查询 求和

#include <cstdio>
// #include <cstdlib>
using namespace std;
#define N (50000+5)
int arr[N];
int tree[N<<2];
void push_up(int root){ // 向上传播
    tree[root] = tree[root<<1] + tree[root<<1|1];
}
void build_tree(int left,int right,int root){
    if(left == right){
        tree[root] = arr[left];
    }else{
        int mid = (left+right)>>1;
        build_tree(left,mid,root<<1);
        build_tree(mid+1,right,root<<1|1);
        push_up(root);
    }
}

void update(int left,int right,int root,int pos,int delta){ // 单点修改
    if(left == right){
        tree[root] += delta;
    }else{
        int mid = (left+right)>>1;
        if(pos <= mid){
            update(left,mid,root<<1,pos,delta);
        }else{
            update(mid+1,right,root<<1|1,pos,delta);
        }
        push_up(root);
    }
}

int query(int left,int right,int root,int ask_left,int ask_right){
    if(ask_right < left || ask_left > right){ // 待查询区间与当前区间交集为空
        return 0;
    }
    if(left >= ask_left && ask_right >= right){ // 待查询区间包含当前区间
        return tree[root];
    }
    int mid = (left+right)>>1;
    return query(left,mid,root<<1,ask_left,ask_right) + query(mid+1,right,root<<1|1,ask_left,ask_right);
}
int main(){
    int T;
    scanf("%d",&T);
    for(int g = 1; g <= T; g++){
        printf("Case %d:\n",g);
        int n;
        scanf("%d",&n);
        for(int i = 1; i <= n; i++){
            scanf("%d",&arr[i]);
        }
        build_tree(1,n,1);
        char cmd[10];
        int i,j;
        while(1){
            scanf("%s",cmd);
            if(cmd[0] == 'Q'){
                scanf("%d%d",&i,&j);
                printf("%d\n",query(1,n,1,i,j));
            }else if(cmd[0] == 'A'){
                scanf("%d%d",&i,&j);
                update(1,n,1,i,j);
            }else if(cmd[0] == 'S'){
                scanf("%d%d",&i,&j);
                update(1,n,1,i,-j);
            }else{
                break;
            }
        }
    }
    // system("pause");
    return 0;
}

HDU - 1754 -I Hate It

本题为单点修改+区间查询 最值

#include <cstdio>
#include <cstdlib>
using namespace std;
#define N (200000+5)
#define MAX(a,b) (a>b?a:b)
int arr[N];
int tree[N<<2];
void push_up(int root){ // 向上传播
    int a = tree[root<<1];
    int b = tree[root<<1|1];
    tree[root] = MAX(a,b); 
}
void build_tree(int left,int right,int root){
    if(left == right){
        tree[root] = arr[left];
    }else{
        int mid = (left+right)>>1;
        build_tree(left,mid,root<<1);
        build_tree(mid+1,right,root<<1|1);
        push_up(root);
    }
}

void update(int left,int right,int root,int pos,int delta){ // 单点修改
    if(left == right){
        tree[root] = delta;
    }else{
        int mid = (left+right)>>1;
        if(pos <= mid){
            update(left,mid,root<<1,pos,delta);
        }else{
            update(mid+1,right,root<<1|1,pos,delta);
        }
        push_up(root);
    }
}

int query(int left,int right,int root,int ask_left,int ask_right){
    if(ask_right < left || ask_left > right){ // 待查询区间与当前区间交集为空
        return 0;
    }
    if(left >= ask_left && ask_right >= right){ // 待查询区间包含当前区间
        return tree[root];
    }
    int mid = (left+right)>>1;
    int ll = query(left,mid,root<<1,ask_left,ask_right);
    int rr = query(mid+1,right,root<<1|1,ask_left,ask_right);
    return MAX(ll,rr);
}
int main(){
    int n,q;
    while(scanf("%d%d",&n,&q)!=EOF){
        for(int i = 1; i <= n; i++){
            scanf("%d",&arr[i]);
        }
        build_tree(1,n,1);
        char cmd[10];
        int i,j;
        while(q--){
            scanf("%s",cmd);
            if(cmd[0] == 'Q'){
                scanf("%d%d",&i,&j);
                printf("%d\n",query(1,n,1,i,j));
            }else{
                scanf("%d%d",&i,&j);
                update(1,n,1,i,j);
            }
        }
    }
    // system("pause");
    return 0;
}

POJ - 3468 - A Simple Problem With Integers

注意一点:

只要某个结点的祖先结点没有lazy标记,那么这个结点的值就是正确的

当访问一个到一个有lazy标记的结点,就顺便将它的lazy标记传播到下一层

#include <cstdio>
// #include <cstdlib>
using namespace std;
#define N 100000+5
typedef long long ll;
ll arr[N];
ll tree[N<<2];
ll lazy[N<<2];

void push_up(int root){ // 向上传播,更新根节点的值
    tree[root] = tree[root<<1] + tree[root<<1|1];
}
void push_down(int left,int right,int root){ // lazy标记向下传播
    if(lazy[root]){
        int mid = (left+right)>>1;
        int left_root = root<<1;
        int right_root = root<<1|1;
        tree[left_root] += lazy[root] * (mid-left+1); // 更新子结点的值,但根结点的值还未更新,还需要push_up操作
        tree[right_root] += lazy[root] * (right-mid);
        lazy[left_root] += lazy[root]; // lazy标记向下传播
        lazy[right_root] += lazy[root];
        lazy[root] = 0;
    }
}
void build_tree(int left,int right,int root){
    if(left == right){
        tree[root] = arr[left];
    }else{
        int mid = left+right>>1;
        build_tree(left,mid,root<<1);
        build_tree(mid+1,right,root<<1|1);
        push_up(root);
    }
}

void update(int left,int right,int root,int update_left,int update_right,ll delta){
    if(update_left <= left && update_right >= right){ // 更新区间包含当前区间
        tree[root] += delta * (right-left+1); 
        lazy[root] += delta;
    }else{ // 更新区间不能包含当前区间
        int mid = (left+right)>>1;
        push_down(left,right,root);
        if(update_left <= mid){ // 在左子树中存在更新区间
            update(left,mid,root<<1,update_left,update_right,delta);
        }
        if(update_right > mid){ // 在右子树中存在更新区间
            update(mid+1,right,root<<1|1,update_left,update_right,delta);
        }
        push_up(root);
    }
}

ll query(int left,int right,int root,int query_left,int query_right){
    if(query_left <= left && query_right >= right){
        return tree[root];
    }else{
        push_down(left,right,root);
        int mid = (left+right)>>1;
        ll ans = 0;
        if(query_left <= mid){
            ans += query(left,mid,root<<1,query_left,query_right);
        }
        if(query_right > mid){
            ans += query(mid+1,right,root<<1|1,query_left,query_right);
        }
        return ans;
    }
}
int main(){
    int n,q;
    int l,r;
    ll delta;
    char cmd[5];
    scanf("%d%d",&n,&q);
    for(int i = 1; i <= n; i++){
        scanf("%lld",&arr[i]);
    }
    build_tree(1,n,1);
    while(q--){
        scanf("%s",cmd);
        if(cmd[0] == 'Q'){
            scanf("%d%d",&l,&r);
            printf("%lld\n",query(1,n,1,l,r));
        }else{
            scanf("%d%d%lld",&l,&r,&delta);
            update(1,n,1,l,r,delta);
        }
    }
    // system("pause");
    return 0;
}
posted @ 2020-10-28 10:59  popozyl  阅读(103)  评论(0编辑  收藏  举报