• 线段树


    1结构
    线段树是一个平衡的二元树,所有叶子到根的距离最多只差1。令整个区间的长度为N,则其有N个叶节点,每个叶节点代表一个单位区间,每个内部结点代表的区间为其两个儿子代表区间的联集。
    
    2基本操作
    线段树所要提供的是查询一个区间内的资讯,并允许修改操作。要使用线段树,此资讯必须满足对于区间与位于区间内的一点,要可以由、求得。例如范围最值查询即符合此条件。
    
    代码中, rt指的是root, 当前子树的根节点; l, r指的是当前子树所统计的区间利用完全二叉堆的性质来保存节点编号, 所以rt << 1是左子树的节点, rt << 1 | 1是右子树的节点在查询和成端更新操作中的L和R是指修改或者查询的区间
    
    
    //线段树 
    #include<bits/stdc++.h>
    using namespace std;
    
    typedef long long ll;
    
    const int N=2e5+9; 
    int n,m;
    ll sum[N<<2]/*4倍空间*/,tag[N<<2];
    
    
    //将子节点的值更新到父节点
    void pushup(int u){
        sum[u]=sum[u<<1]+sum[u<<1|1];
    }
    
    void buildtree(int u,int ul,int ur){
        if(ul==ur){//如果是叶节点 
            scanf("%ll",sum+u);
            return;
        }
        int mid=ul+ur>>1;
        buildtree(u<<1,ul,mid);
        buildtree(u<<1|1,mid+1,ur);
        pushup(u);
    }
    
    void update(int u,int ul,int ur,int mx){
        tag[u]+=mx;
        sum[u]+=(ll)mx*(ur-ul+1);
    }
    
    
    //节点懒惰标记下传
    void pushdown(int u,int ul,int ur){
        if(tag[u]){
            int mid=ul+ur>>1;
            update(u<<1,ul,mid,tag[u]);
            update(u<<1|1,mid+1,ur,tag[u]);
            tag[u]=0;
        }
    }
    
    void modify(int u,int ul,int ur,int ml,int mr,int mx){
        if(ml<=ul&&ur<=mr){
            update(u,ul,ur,mx);
            return;
        }
        pushdown(u,ul,ur);
        int mid=ul+ur>>1;
        if(ml<=mid)
            modify(u<<1,ul,mid,ml,mr,mx);
        if(mr>=mid+1)
            modify(u<<1|1,mid+1,ur,ml,mr,mx);
        pushup(u);
    }
    
    ll query(int u,int ul,int ur,int ml,int mr){
        if(ml<=ul&&ur<=mr)
            return sum[u];
        pushdown(u,ul,ur);
        int mid=ul+ur>>1;
        ll s=0;
        if(ml<=mid)
            s+=query(u<<1,ul,mid,ml,mr);
        if(mr>=mid+1)
            s+=query(u<<1|1,mid+1,ur,ml,mr);
        return s;
    }
    
    int main(){
        scanf("%d%d",&n,&m);
        buildtree(1,1,n);
        while(m--){
            int opt,x,y,z;
            scanf("%d%d%d",&opt,&x,&y);
            if(opt==0){
                scanf("%d",&z);
                modify(1,1,n,x,y,z);//修改函数 
            } else{
                printf("%ll
    ",query(1,1,n,x,y));
            } 
        }
    }
     
  • 相关阅读:
    poj 2728 Desert King(最小比率生成树,迭代法)
    HDU
    hud 2089 不要62 (数位dp)
    食物链(带全并查集)
    docNet基础学完感想
    zoj 1081 (改进的弧长算法)(转)
    zoj 1962 How Many Fibs?(字符串化为数字处理)
    zoj 1109 zoj 1109 Language of FatMouse(字典树)
    iOS开发网络数据之AFNetworking使用
    iOS 使用AFNetworking
  • 原文地址:https://www.cnblogs.com/aprincess/p/11623867.html
Copyright © 2020-2023  润新知