zoukankan      html  css  js  c++  java
  • 线段树维护区间和

    新学习了线段树,打了线段树维护区间和的模板。

    #include<cstdio>
    
    #define min(a,b) (a<b?a:b)
    #define max(a,b) (a>b?a:b)
    
    #define MAXNUM 100001
    #define INF ((1<<31)-1)
    #define left(a) (a<<1)
    #define right(a) ((a<<1)+1)
    
    int n,q;
    long long arr[MAXNUM];
    
    struct SegTreeNode{
        long long val;
        long long lazy;
        SegTreeNode(){
            val=0;
            lazy=0;
        }
    }node[MAXNUM*5];
    
    void tree_update(int root){
        long long a=node[left(root)].val,b=node[right(root)].val;
        node[root].val=a+b;
        return;
    }
    void lazy_push(int root,int l,int r){
        node[left(root)].lazy+=node[root].lazy;
        node[right(root)].lazy+=node[root].lazy;
        node[root].val+=(r-l+1)*node[root].lazy;
        node[root].lazy=0;
    }
    void tree_build(int root,long long arr[],int bl,int br){
        node[root].lazy=0;
        if(bl==br) node[root].val=arr[bl];
        else{
            int mid=(bl+br)/2;
            tree_build(left(root),arr,bl,mid);
            tree_build(right(root),arr,mid+1,br);
            tree_update(root);
        }
        return;
    }
    void tree_add(int root,int al,int ar,int l,int r,long long k){
        if(r<al||ar<l) return;
        if(l==al&&r==ar){
            node[root].lazy+=k;
            return;
        }
        lazy_push(root,l,r);
        int mid=(l+r)/2;
        if(mid>=al) tree_add(left(root),al,min(mid,ar),l,mid,k);
        if(mid<ar) tree_add(right(root),max(mid+1,al),ar,mid+1,r,k);
        lazy_push(left(root),l,mid);
        lazy_push(right(root),mid+1,r);
        tree_update(root);
        return;
    }
    long long ques(int root,int ql,int qr,int l,int r){
        if(l>r) return 0;
        if(l==ql&&r==qr) return node[root].lazy*(r-l+1)+node[root].val;
        lazy_push(root,l,r);
        int mid=(l+r)/2;
        long long ans=0;
        if(mid>=ql) ans+=ques(left(root),ql,min(mid,qr),l,mid);
        if(mid<qr) ans+=ques(right(root),max(mid+1,ql),qr,mid+1,r);
        return ans;
    }
    
    int main(){
        scanf("%d%d",&n,&q);
        for(int i=1;i<=n;i++) scanf("%lld",&arr[i]);
        tree_build(1,arr,1,n);
        while(q--){
            int p,x,y;
            long long k;
            scanf("%d",&p);
            if(p==1){
                scanf("%d%d%lld",&x,&y,&k);
                tree_add(1,x,y,1,n,k);
            }
            if(p==2){
                scanf("%d%d",&x,&y);
                printf("%lld\n",ques(1,x,y,1,n));
            }
        }
        return 0;
    }
    代码

    就是这样了。

  • 相关阅读:
    第三章 操作符
    exit函数
    详解C++ friend关键字
    放假了,暂告一段落,迎接研究生
    使用const 提高函数的健壮性
    使用断言assert
    对return 语句的正确性和效率进行检查
    函数堆栈
    somethings about QSplitter
    引用和引用参数
  • 原文地址:https://www.cnblogs.com/halifuda/p/7834621.html
Copyright © 2011-2022 走看看