zoukankan      html  css  js  c++  java
  • P3373 【模板】线段树 2 (未完待续)

    P3373 【模板】线段树 2

    强烈安利这个大佬 超赞!!!

    题解

    本来以为这个题拿着线段树1的板子改改就好了,但是发现事情并没有那么简单,改了两天。。。

    我们看到这个题其实涉及啦乘法和加法两种运算,如何把这两种运算同时塞到懒标记当中呢??似乎有些困难

    !!!那么我们可以开两个懒标记啊,一个记录乘法mul[ ],一个记录加法add[ ]

    初始化

    add[ ] 初始化当然为0,不加减任何数

    mul[ ] 初始化当然为1 ,不乘任何数

    标记下传以及ADD运算的时候两者都要维护

    运算顺序

    当我们乘法和加法的懒标记都有的时候

    是先加后乘呢?

    还是先乘后加呢?

    ans:先乘后加

    注意

    这个题数据算着算着就很大了,一定要都开long long

    还有一点就是忽略掉 if (add [ ] ==0)

    代码

    #include<bits/stdc++.h>
    
    using namespace std;
    
    #define ll long long    //一定要开long long ,不然会炸 
    const int maxn=1e7+10;
    ll n,m,x,y,v,opr,mod;
    ll a[maxn],add[maxn*4],mul[maxn*4];
    //add[]加法懒标记,mul[]乘法懒标记 
    ll sum[maxn*4]; 
    //前缀和 
    ll ans;
    
    void build(ll k,ll l,ll r)   //建树 
    {
        mul[k]=1;  //初始化乘法前缀和为1,表示不变 
        if(l==r)
        {
            sum[k]=a[l];  return ;
        } 
        ll mid=(l+r)>>1;
        build(k<<1,l,mid);
        build(k<<1|1,mid+1,r);
        sum[k]=(sum[k<<1]+sum[k<<1|1])%mod;
    }
    
    void Add(ll k,ll l,ll r,ll mulp,ll sump)   //处理懒标记,先乘后加 
    {
        sum[k]=(sum[k]*mulp+(r-l+1)*sump)%mod;
        add[k]=(add[k]*mulp+sump)%mod;
        mul[k]=(mul[k]*mulp)%mod;
    }
    
    void pushdown(ll k,ll l,ll r,ll mid)  //标记下传 
    {
    //    if(add[k]==0) return ;
        Add(k<<1,l,mid,mul[k],add[k]);
        Add(k<<1|1,mid+1,r,mul[k],add[k]);
        add[k]=0;   //清空懒标记 
        mul[k]=1;
    }
    
    void modifymul(ll k,ll l,ll r,ll x,ll y,ll v)  //乘法区间修改 
    {
        if(x<=l&&r<=y) return Add(k,l,r,v,0);
        ll mid=(l+r)>>1;
        pushdown(k,l,r,mid);
        if(x<=mid) modifymul(k<<1,l,mid,x,y,v);
        if(mid<y) modifymul(k<<1|1,mid+1,r,x,y,v);
        sum[k]=(sum[k<<1]+sum[k<<1|1])%mod;  //维护前缀和 
    }
    
    void modifysum(ll k,ll l,ll r,ll x,ll y,ll v)  //加法区间修改 
    {
        if(x<=l&&r<=y) return Add(k,l,r,1,v);
        ll mid=(l+r)>>1;
        pushdown(k,l,r,mid);
        if(x<=mid) modifysum(k<<1,l,mid,x,y,v);
        if(mid<y) modifysum(k<<1|1,mid+1,r,x,y,v);
        sum[k]=(sum[k<<1]+sum[k<<1|1])%mod;
    }
    
    long long query(ll k,ll l,ll r,ll x,ll y)  //区间询问 
    {
        if(x<=l&&r<=y) return sum[k];
        ll mid=(l+r)>>1;
        ll res=0;
        pushdown(k,l,r,mid);
        if(x<=mid) res+=query(k<<1,l,mid,x,y);
        if(mid<y) res+=query(k<<1|1,mid+1,r,x,y);
        return res%mod;
    }
    
    int main()
    {
        scanf("%ld%ld%ld",&n,&m,&mod);
        for(ll i=1;i<=n;i++)
          scanf("%ld",&a[i]);
        
        build(1,1,n);
        
        for(ll i=1;i<=m;i++)
        {
            scanf("%ld%ld%ld",&opr,&x,&y);
            if(opr==1)
            {
                scanf("%ld",&v);
                modifymul(1,1,n,x,y,v);
            }
            if(opr==2)
            {
                scanf("%ld",&v);
                modifysum(1,1,n,x,y,v);
            }
            if(opr==3)
            {
                ans=query(1,1,n,x,y);
                printf("%ld
    ",ans%mod);
            }
        }
        
        return 0;
    }
  • 相关阅读:
    Apache-Shiro
    Linux下的Nginx安装
    Linux安装Redis
    Linux安装ftp组件vsftpd
    Spring笔记(二)
    Spring笔记(一)
    MySQL事务
    rocketMQ基本理解
    2018面试题小结
    v-if和v-show
  • 原文地址:https://www.cnblogs.com/xiaoyezi-wink/p/11105832.html
Copyright © 2011-2022 走看看