• bzoj 1798(线段树)


    传送门

    分析:

    因为同时涉及两种区间更新操作,故考虑用两种$lazytag$去打标记。

    而在我们进行区间加和区间乘的时候,我们会发现,因为乘法的优先级较加法的优先级要高,因此,为了方便处理,我们优先选择下放乘法标记。

    同时我们需要注意,在我们下放乘法标记$mul$的时候,如果当前区间存在加法标记$add$,则我们需要在$add$的基础上乘上$mul$

    #include <bits/stdc++.h>
    using namespace std;
    const int maxn=100005;
    int mod;
    typedef long long ll;
    struct St{
        int rt,len;
        ll mul,sum,add;
    }tr[maxn<<2];
    int a[maxn];
    void push_up(int rt){
        tr[rt].sum=(tr[rt<<1].sum+tr[rt<<1|1].sum)%mod;
    }
    void push_down(int rt){
        if(tr[rt].mul!=1){
            tr[rt<<1].mul=(tr[rt<<1].mul*tr[rt].mul)%mod;
            tr[rt<<1|1].mul=(tr[rt<<1|1].mul*tr[rt].mul)%mod;
            tr[rt<<1].add=(tr[rt<<1].add*tr[rt].mul)%mod;
            tr[rt<<1|1].add=(tr[rt<<1|1].add*tr[rt].mul)%mod;
            tr[rt<<1].sum=(tr[rt<<1].sum*tr[rt].mul)%mod;
            tr[rt<<1|1].sum=(tr[rt<<1|1].sum*tr[rt].mul)%mod;
            tr[rt].mul=1;
        }
        if(tr[rt].add){
            tr[rt<<1].add=(tr[rt<<1].add+tr[rt].add)%mod;
            tr[rt<<1|1].add=(tr[rt<<1|1].add+tr[rt].add)%mod;
            tr[rt<<1].sum=(tr[rt<<1].sum+tr[rt<<1].len*tr[rt].add%mod)%mod;
            tr[rt<<1|1].sum=(tr[rt<<1|1].sum+tr[rt<<1|1].len*tr[rt].add%mod)%mod;
            tr[rt].add=0;
        }
    }
    void build(int l,int r,int rt){
        tr[rt].len=r-l+1;
        tr[rt].mul=1;
        tr[rt].add=0;
        if(l==r){
            tr[rt].sum=a[l];
            return;
        }
        int mid=(l+r)>>1;
        build(l,mid,rt<<1);
        build(mid+1,r,rt<<1|1);
        push_up(rt);
    }
    void update1(int L,int R,int l,int r,int rt,int x){
        if(L<=l&&R>=r){
            tr[rt].sum=tr[rt].sum+x*tr[rt].len%mod;
            tr[rt].add=(tr[rt].add+x)%mod;
            return ;
        }
        push_down(rt);
        int mid=(l+r)>>1;
        if(L<=mid) update1(L,R,l,mid,rt<<1,x);
        if(R>mid)  update1(L,R,mid+1,r,rt<<1|1,x);
        push_up(rt);
    }
    void update2(int L,int R,int l,int r,int rt,int x){
        if(L<=l&&R>=r){
            tr[rt].mul=tr[rt].mul*x%mod;
            tr[rt].add=tr[rt].add*x%mod;
            tr[rt].sum=tr[rt].sum*x%mod;
            return;
        }
        int mid=(l+r)>>1;
        push_down(rt);
        if(L<=mid) update2(L,R,l,mid,rt<<1,x);
        if(R>mid)  update2(L,R,mid+1,r,rt<<1|1,x);
        push_up(rt);
    }
    ll query(int L,int R,int l,int r,int rt){
        if(L<=l&&R>=r){
            return tr[rt].sum%mod;
        }
        int mid=(l+r)>>1;
        push_down(rt);
        ll res=0;
        if(L<=mid) res=(query(L,R,l,mid,rt<<1)+res)%mod;
        if(R>mid) res=(query(L,R,mid+1,r,rt<<1|1)+res)%mod;
        return res;
    }
    int main()
    {
        int n,m;
        scanf("%d%d",&n,&mod);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }
        build(1,n,1);
        scanf("%d",&m);
        while(m--){
            int op,l,r,num;
            scanf("%d%d%d",&op,&l,&r);
            if(op==1){
                scanf("%d",&num);
                update2(l,r,1,n,1,num);
            }
            else if(op==2){
                scanf("%d",&num);
                update1(l,r,1,n,1,num);
            }
            else{
                printf("%lld
    ",query(l,r,1,n,1)%mod);
            }
        }
        return 0;
    }
    
  • 相关阅读:
    航班预定统计(差分数组+前缀和)
    救生艇
    Xcode 的正确打开方式——Debugging
    多次页面跳转后pop回主界面的问题
    理解Bitcode:一种中间代码
    使用AFNetWorking读取JSON出现NSCocoaErrorDomain Code=3840的解决方法
    No identities are available for signing的解决方法
    Aufree/trip-to-iOS
    Alcatraz -- 一个神奇的管理插件的Xcode插件
    GenericKeychain
  • 原文地址:https://www.cnblogs.com/Chen-Jr/p/11007130.html
Copyright © 2020-2023  润新知