• 线段树区间更新+区间求和模板(数组实现)洛谷p3372,p3373


    模板题目1:https://www.luogu.org/problemnew/show/P3372

    懒惰标记讲解:https://www.cnblogs.com/wushengyang/p/11194456.html

    这题目只需要用一个懒惰标记,不用考虑顺序。

    AC代码:

    #include <stdio.h>
    #include <iostream>
    #include <cstdlib>
    #include <cmath>
    #include <cctype>
    #include <string>
    #include <cstring>
    #include <algorithm>
    #include <stack>
    #include <queue>
    #include <set>
    #include <map>
    #include <ctime>
    #include <vector>
    #include <fstream>
    #include <list>
    #include <iomanip>
    #include <numeric>
    using namespace std;
    typedef long long int ll;
    typedef unsigned long long int ull;
    const int inf = 0x3f3f3f3f;
    int dir[8][2]={{1,0},{0,1},{1,1},{1,-1},{-1,1},{-1,-1},{0,-1},{-1,0}};
    #define pi acos(-1)
    #define me0(s) memset(s,0,sizeof(s))
    #define me1(s) memset(s,1,sizeof(s))
    #define mef(s) memset(s,-1,sizeof(s))
    #define meinf(s) memset(s,inf,sizeof(s))
    const int N=100005;
    #define ls rt<<1
    #define rs rt<<1|1
    ll a[N],sum[N*4],lazy[N*4];
    void push_up(ll rt){
        sum[rt]=sum[ls]+sum[rs]; //更新和
    }
    void push_down(ll m,ll rt){ //m为总区间长度
        if(lazy[rt]){ //如果懒惰标记存在
            lazy[ls]+=lazy[rt]; //左子树懒惰标记等于其本身加父亲节点的值
            lazy[rs]+=lazy[rt];
            sum[ls]+=lazy[rt]*(m-(m>>1)); //懒惰标记乘个数
            sum[rs]+=lazy[rt]*(m>>1);
            lazy[rt]=0;
        }
    }
    void build(ll l,ll r,ll rt){ //建树
        lazy[rt]=0; //可以建树直接赋值0
        if(l==r){
            sum[rt]=a[l];
            return ;
        }
        ll m=(l+r)>>1;
        build(l,m,ls);
        build(m+1,r,rs);
        push_up(rt);
    }
    void update(ll L,ll R,ll c,ll l,ll r,ll rt){//区间更新[l,r],[L,R]代表总区间
        if(l<=L&&r>=R){
            lazy[rt]+=c; //更新懒惰标记
            sum[rt]+=c*(R-L+1); //更新节点存的sum值
            return ;
        }
        push_down(R-L+1,rt); //所有的节点都更新一遍lazy标记
        ll m=(L+R)>>1; //总区间的一半
        if(l<=m) update(L,m,c,l,r,ls); //注意这里递归的是总区间为变量
        if(r>m) update(m+1,R,c,l,r,rs);
        push_up(rt);
    }
    ll query(ll L,ll R,ll l,ll r,ll rt){ //[l,r]区间
        if(l<=L&&r>=R) return sum[rt];
        push_down(R-L+1,rt);
        ll m=(L+R)>>1; //总区间的一半
        ll ans=0;
        if(l<=m) ans+=query(L,m,l,r,ls); //这个递归的也是总区间变量
        if(r>m) ans+=query(m+1,R,l,r,rs);
        return ans;
    }
    int main(int argc, char * argv[]) 
    {
        std::ios::sync_with_stdio(false);
        int n,m;
        cin>>n>>m;
        for(int i=1;i<=n;i++) cin>>a[i];
        build(1,n,1);
        while(m--){
            ll op,x,y,k;
            cin>>op;
            if(op==1){
                cin>>x>>y>>k;
                update(1,n,k,x,y,1);
            }
            if(op==2){
                cin>>x>>y;
                cout<<query(1,n,x,y,1)<<endl;
            }
        }
        return 0;
    }

    模板题目2:https://www.luogu.org/problemnew/show/P3373

    这道题目由于存在多种区间更改操作,所以懒惰标记之间有关系,比如如果先求加法的话给他加上一个懒惰标记,再做乘法的话以前的懒惰标记加的那一部分也同时需要做一次乘法,这样才能完整。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long int ll;
    typedef unsigned long long int ull;
    const int inf = 0x3f3f3f3f;
    int dir[8][2]={{1,0},{0,1},{1,1},{1,-1},{-1,1},{-1,-1},{0,-1},{-1,0}};
    #define pi acos(-1)
    #define ls rt<<1
    #define rs rt<<1|1
    #define me0(s) memset(s,0,sizeof(s))
    #define me1(s) memset(s,1,sizeof(s))
    #define mef(s) memset(s,-1,sizeof(s))
    #define meinf(s) memset(s,inf,sizeof(s))
    const int N=100005;
    ll mod;
    ll a[N],sum[N*4],lazya[N*4],lazym[N*4]; //lazya存的加的数,lazym存乘
    void push_up(int rt){
        sum[rt]=(sum[ls]+sum[rs])%mod;
    }
    void push_down(ll m,ll rt){
        lazya[ls]=(lazya[rt]+lazya[ls]*lazym[rt])%mod;//乘法的分配率
        lazya[rs]=(lazya[rt]+lazya[rs]*lazym[rt])%mod;
        lazym[ls]=(lazym[rt]*lazym[ls])%mod; //懒惰标记直接乘
        lazym[rs]=(lazym[rt]*lazym[rs])%mod;
        sum[ls]=(lazya[rt]*(m-(m>>1))+sum[ls]*lazym[rt])%mod;
        sum[rs]=(lazya[rt]*(m>>1)+sum[rs]*lazym[rt])%mod;
        lazya[rt]=0;
        lazym[rt]=1;
    }
    void build(ll l,ll r,ll rt){
        lazym[rt]=1; //初始化乘值
        if(l==r){
            sum[rt]=a[l];
            return ;
        }
        ll m=(l+r)>>1;
        build(l,m,ls);
        build(m+1,r,rs);
        push_up(rt);
    }
    void update_a(ll L,ll R,ll c,ll l,ll r,ll rt){//做加法
        if(l<=L&&r>=R){
            sum[rt]=(sum[rt]+(R-L+1)*c)%mod;
            lazya[rt]=(c+lazya[rt])%mod;
            return ;
        }
        push_down(R-L+1,rt);
        ll m=(L+R)>>1;
        if(l<=m) update_a(L,m,c,l,r,ls);
        if(r>m) update_a(m+1,R,c,l,r,rs);
        push_up(rt);
    }
    void update_m(ll L,ll R,ll c,ll l,ll r,ll rt){//做乘法
        if(l<=L&&r>=R){
            sum[rt]=(sum[rt]*c)%mod;
            lazya[rt]=(c*lazya[rt])%mod;
            lazym[rt]=(c*lazym[rt])%mod;
            return ;
        }
        push_down(R-L+1,rt);
        ll m=(L+R)>>1;
        if(l<=m) update_m(L,m,c,l,r,ls);
        if(r>m) update_m(m+1,R,c,l,r,rs);
        push_up(rt);
    }
    ll query(ll L,ll R,ll l,ll r,ll rt){
        if(l<=L&&r>=R){
            return sum[rt];
        }
        push_down(R-L+1,rt);
        ll m=(L+R)>>1;
        ll ans=0;
        if(l<=m) ans=(ans+query(L,m,l,r,ls))%mod;
        if(r>m) ans=(ans+query(m+1,R,l,r,rs))%mod;
        return ans%mod;
    }
    int main(int argc, char * argv[]) 
    {
        std::ios::sync_with_stdio(false);
        ll n,m,x,y,k,op;
        cin>>n>>m>>mod;
        for(int i=1;i<=n;i++) cin>>a[i];
        build(1,n,1);
        while(m--){
            cin>>op;
            if(op==1){
                cin>>x>>y>>k;
                update_m(1,n,k,x,y,1);
            }
            if(op==2){
                cin>>x>>y>>k;
                update_a(1,n,k,x,y,1);
            }
            if(op==3){
                cin>>x>>y;
                cout<<query(1,n,x,y,1)<<endl;
            }
        }
        return 0;
    }
  • 相关阅读:
    python之pymysql的使用
    python 之 Apollo
    python 之 RabbitMQ
    python之内置sqlite3
    pyQt5之2048小游戏
    VSCode 下载速度慢问题解决
    Redis 缓存穿透 + 缓存雪崩 + 缓存击穿的原因和解决方案
    部门优化
    Cpu_Limit.sh
    Autoback-xtraback.sh
  • 原文地址:https://www.cnblogs.com/wushengyang/p/11196119.html
Copyright © 2020-2023  润新知