• 线段树模板


    https://oi-wiki.org/ds/seg/

    poj3468

    区间增减值,区间和。

    线段树思想:利用二叉树将每一个区间所需要的值都记录下来。

    lazy思想:延迟对叶子节点的修改,要用到的时候才真的去修改,lazy数组记录修改的值。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    const int maxn = 1e6+10;
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    
    ll a[maxn];
    ll d[maxn<<2];
    ll lazy[maxn<<2];
    
    void PushDown(ll rt,ll l,ll r)   //下放懒惰标记 
    {
        if(lazy[rt])
        {
        lazy[rt<<1] +=lazy[rt];    //左儿子懒惰标记加上当前父亲的懒惰值
        lazy[rt<<1|1]+=lazy[rt];   //右儿子懒惰标记加上当前父亲的懒惰值
        ll m=(l+r)>>1;
        d[rt<<1]+=lazy[rt]*(m-l+1); //左儿子的区间和加上父亲的懒惰标记值乘区间长度
        d[rt<<1|1]+=lazy[rt]*(r-m); //右儿子的区间和加上父亲的懒惰标记值乘区间长度
        lazy[rt] = 0;   //父亲懒惰值置0,懒惰标记下放完成
        }
    }
    
    void build(ll l,ll r,ll rt)
    {
        //len[rt]=l-r+1;    可以用一个数组纪录每个节点对应的区间长度
        if(l==r)
        {
            d[rt]=a[l];return;
        }
        ll m=(l+r)>>1;
        build(lson);
        build(rson);
        d[rt]=d[rt<<1]+d[rt<<1|1];  //求和,可相应的改为max min等函数
    }
    
    void update(ll L,ll R,ll l,ll r,ll rt,ll val)//[L,R]目标区间 [l,r]当前区间
    {
        if(L<=l && r<=R)   //如果当前区间在目标区间内
        {
            lazy[rt]+=val;  //打上懒惰标记
            d[rt]+=(r-l+1)*val; return;  //区间和加上区间长度乘val
        }
        PushDown(rt,l,r);      //下放懒惰标记 
        ll m=(l+r)>>1;
        if(m>=L)
        update(L,R,lson,val); //[l,L,m,r]   //说明与左儿子有交集
        if(R>m) 
        update(L,R,rson,val); //[l,m,R,r]   //说明与右儿子有交集
        d[rt]=d[lson]+d[rson];  //向上更新
    }
    
    ll query(ll L,ll R,ll l,ll r,ll rt)
    {
        if(L<=l && r<=R)
        {
            return d[rt];
        }
        PushDown(rt,l,r);
        ll m=(l+r)>>1;
        ll res=0;
        if(L <= m) 
        res += query(L,R,lson);  
        if(R > m) 
        res += query(L,R,rson); 
        return res;
    }
    
    int main() 
    {
        ll N,Q;
        scanf("%lld%lld",&N,&Q);
        for(int i=1;i<=N;i++)
        scanf("%lld",&a[i]);
        build(1,N,1);
        char ope[5];
        ll l,r,val;
        while(Q--)
        {   
            scanf("%s",ope);
            if(ope[0]=='Q')
            {
                scanf("%lld%lld",&l,&r);
                printf("%lld
    ",query(l,r,1,N,1));
            }
            else
            {
                scanf("%lld%lld%lld",&l,&r,&val);
                update(l,r,1,N,1,val);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    POJ 题目2750 Potted Flower(线段树求环型区间中连续区间的最大和)
    即使没人看我们也要坚持写Blog
    鸟哥的Linux私房菜-----7、硬件管理
    android createbitmap函数内存溢出,求解怎样进行处理out of memory溢出问题
    hdu4614Vases and Flowers 线段树
    安装npm及cnpm(Windows)
    安装npm及cnpm(Windows)
    安装npm及cnpm(Windows)
    Echarts设置点击事件
    Vs Code中炫酷写代码插件Power Mode的安装配置
  • 原文地址:https://www.cnblogs.com/chilkings/p/11939332.html
Copyright © 2020-2023  润新知