zoukankan      html  css  js  c++  java
  • 线段树

    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));
            } 
        }
    }
     
  • 相关阅读:
    滚动新闻的实现
    使用DLC(Dynamic Loader Compatibility)函数提取iPhone当前运营商信号的强度
    iOS设备中WiFi、蓝牙和飞行模式的开启与关闭
    如何在Typora中使用流程图
    连接池的使用场景
    Mybatisplus入门教程(一)
    mybatis第一篇
    Mybatis需要注意的细节
    测试代码着色插件
    (转)企业Elearning的产业链与业务模式
  • 原文地址:https://www.cnblogs.com/aprincess/p/11623867.html
Copyright © 2011-2022 走看看