• 线段树1


    #include<cstdio>
    
    using namespace std;
    
    const int maxn=1e5;
    
    typedef long long int ll;
    
    ll a[maxn];
    
    struct node{
        int v;
        int l,r;
        int tag;
        node *ls,*rs;
        
        inline bool maketag(const ll w){
            v+=(r-l+1)*w;
            tag+=w;
        }
        
        inline void pushup(){
            v=ls->v+rs->v;
        }
        inline void pushdown(){
            if(tag==0)
            return;
            ls->maketag(tag);
            rs->maketag(tag);
            tag=0;
        }
        
      build(const int L,const int R){
        l=L;
        r=R;
        if(l==r){
            tag=0;
            v=a[l];
            ls=rs=NULL;
        }else{
            tag=0;
            int M=(l+r)>>1;
            ls=new node (l,M);
            rs=new node (M+1,r);
            pushup();
        }
        
    }
        
        inline bool inrange(const int L,const int R){
            return (l<=L)&&(r<=R);
        }
        
        inline bool outrange(const int L,const int R){
            return (l>R)||(r<L);
        }
        
        void upd(const int L,const int R,const ll w){
            if(inrange(L,R)){
                maketag(tag);
            }else if(!outrange(L,R)){
                pushdown();
                ls->upd(L,R,w);
                rs->upd(L,R,w);
                pushup();
            }
        }
        
        ll qry(const int L,const int R){
            if(inrange(L,R))
            return v;
            if(outofrange(L,R))
            return 0;
            pushdown();
            return ls->qry(L,R)+rs->qry(L,R);
            
        }
        
    };
    
    int main()
    {
        scanf("%d%d",&n,&q);
        
        for(int i=1;i<=n;i++)
        scanf("%lld",a+i);
        
        node *rot=new node(1,n);
        
        for(ll o,x,y,z;q;q--)
        {
            scanf("%lld%lld%lld",&o,&x,&y);
            
            if(o==1)
            {
                scanf("%lld",&z);
                rot->upd(x,y,z);
            }else{
                printf("%lld
    ",rot->qry(x,y));
            }
        }    
        
        return 0;
        
    }

     阿这。。。。感觉空荡荡的那我就加点解释吧。。。pushup和pushdown是对父子节点之间关系进行的操作,子节点更新父节点时需要用递归来实现,maketag涉及到一个巧妙地修改子节点的技巧,即在提供单点修改操作的线段树中,将父节点打上一个标记,表示其子节点的值需要被修改,在下一次访问到子节点的时候,再去改变子节点的值。inline bool inrange。。。。感性理解吧,没啥好说的。upd是单点修改用的函数。

    build用来建立一个树,把新的点创建为叶节点。qry为区间求和的函数。

  • 相关阅读:
    如何在存储过程中临时设置数据库兼容级别
    PHP中如何防止SQL注入
    Android 源码下载
    HDU 2517 棋盘分割
    OceanBase里面的rowkey是什么概念,是由哪些要素构成的?
    JavaScript的递归之更多例子
    C++库研究笔记——生成一组随机数
    Neutron 如何支持多种 network provider
    理解 Neutron Server 分层模型
    Neutron 物理部署方案
  • 原文地址:https://www.cnblogs.com/dairuizhe/p/13246283.html
Copyright © 2020-2023  润新知