zoukankan      html  css  js  c++  java
  • 洛谷3373【模板】线段树2

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

    值和标记都是先乘后加。

    别忘了加的时候乘上区间长度!!!

    我的写法果然是要开4倍数组的。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N=400005;
    typedef long long ll;
    ll a[N],f[N],lamul[N],laplu[N],n,m,p,L,R,k,zs;
    void pushup(ll cnt)
    {
        f[cnt]=f[cnt<<1]+f[cnt<<1|1];
    }
    void pushdown(ll l,ll r,ll cnt)
    {
        ll ls=(cnt<<1),rs=(cnt<<1|1),mid=((l+r)>>1);
        f[ls]=(f[ls]*lamul[cnt]+laplu[cnt]*(mid-l+1))%p;//////
        lamul[ls]=(lamul[ls]*lamul[cnt])%p;
        laplu[ls]=(laplu[ls]*lamul[cnt]+laplu[cnt])%p;
        f[rs]=(f[rs]*lamul[cnt]+laplu[cnt]*(r-mid))%p;//////
        lamul[rs]=(lamul[rs]*lamul[cnt])%p;
        laplu[rs]=(laplu[rs]*lamul[cnt]+laplu[cnt])%p;
        lamul[cnt]=1;laplu[cnt]=0;
    }
    void build(ll l,ll r,ll cnt)
    {
        lamul[cnt]=1;
        if(l==r)
        {
            f[cnt]=a[l];
            return;
        }
        ll mid=((l+r)>>1);
        build(l,mid,cnt<<1);
        build(mid+1,r,cnt<<1|1);
        pushup(cnt);
    }
    void mul(ll l,ll r,ll cnt)
    {
        if(l>=L&&r<=R)
        {
            f[cnt]=(f[cnt]*k)%p;
            lamul[cnt]=(lamul[cnt]*k)%p;
            laplu[cnt]=(laplu[cnt]*k)%p;
            return;
        }
        pushdown(l,r,cnt);
        ll mid=((l+r)>>1);
        if(mid>=L)mul(l,mid,cnt<<1);
        if(mid<R)mul(mid+1,r,cnt<<1|1);
        pushup(cnt);
    }
    void plu(ll l,ll r,ll cnt)
    {
        if(l>=L&&r<=R)
        {
            f[cnt]=(f[cnt]+k*(r-l+1))%p;///////乘长度 
            laplu[cnt]=(laplu[cnt]+k)%p;
            return;
        }
        pushdown(l,r,cnt);
        ll mid=((l+r)>>1);
        if(mid>=L)plu(l,mid,cnt<<1);
        if(mid<R)plu(mid+1,r,cnt<<1|1);
        pushup(cnt);
    }
    ll query(ll l,ll r,ll cnt)
    {
        if(l>=L&&r<=R)
            return f[cnt];
        ll mid=((l+r)>>1),ans=0;
        pushdown(l,r,cnt);
        if(mid>=L)ans+=query(l,mid,cnt<<1);
        if(mid<R)ans+=query(mid+1,r,cnt<<1|1);
        return ans%p;
    }
    int main()
    {
        scanf("%lld%lld%lld",&n,&m,&p);
        for(ll i=1;i<=n;i++)scanf("%lld",&a[i]);
        build(1,n,1);
        for(ll i=1;i<=m;i++)
        {
            scanf("%lld%lld%lld",&zs,&L,&R);
            if(zs==1)
            {
                scanf("%lld",&k);
                mul(1,n,1);
            }
            if(zs==2)
            {
                scanf("%lld",&k);
                plu(1,n,1);
            }
            if(zs==3)
                printf("%lld
    ",query(1,n,1)%p);
        }
        return 0;
    }
  • 相关阅读:
    String空格删除和java删除字符串最后一个字符的几种方法
    Ceph 12.2.0 实践osd 智能分组功能
    Ceph 12.2.0 实践osd 智能分组功能
    Ceph 12.2.0 实践osd 智能分组功能
    Ceph 12.2.0 实践osd 智能分组功能
    取区域/扇区边界点
    取区域/扇区边界点
    取区域/扇区边界点
    取区域/扇区边界点
    解决客户端向服务器数据库传输中文乱码的方法
  • 原文地址:https://www.cnblogs.com/Narh/p/8723363.html
Copyright © 2011-2022 走看看