线段树(标记下传乘法和加法)

时光总嘲笑我的痴心妄想 提交于 2019-12-02 16:21:19

传送门:https://www.luogu.org/problem/P3373

标记下传,这种东西就是在求和和更改的时候进行pushdown把标记(各种标记,类似于寒冰标记、痛苦标记、穹妹标记……)下传,来节省时间。

还是挺简单的,主要问题处在pushdown上但多看看就会了

#include<bits/stdc++.h>
using namespace std;
long long n,m,p;
long long multag[1000009];
long long addtag[1000009];
long long seg[4000009];
long long num[1000009];
inline long long kd()
{
    long long x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+(ch^48);ch=getchar();}
    return x*f;
}
inline long long ls(long long x){return x<<1;}
inline long long rs(long long x){return x<<1|1;}
void build(long long now,long long l,long long r)
{
    addtag[now]=0;
    multag[now]=1;
    if(l==r)
    {
        seg[now]=num[l]%p;
        return;
    }
    long long mid=(l+r)>>1;
    build(ls(now),l,mid);
    build(rs(now),mid+1,r);
    seg[now]=(seg[ls(now)]+seg[rs(now)])%p;
    return;
}
void pushdown(long long now,long long l,long long r)
{
    long long mid=(l+r)>>1;
    seg[ls(now)]=(seg[ls(now)]*multag[now]+addtag[now]*(mid-l+1))%p;
    seg[rs(now)]=(seg[rs(now)]*multag[now]+addtag[now]*(r-mid))%p;
    multag[ls(now)]=(multag[ls(now)]*multag[now])%p;
    multag[rs(now)]=(multag[rs(now)]*multag[now])%p;
    addtag[ls(now)]=(addtag[ls(now)]*multag[now]+addtag[now])%p;
    addtag[rs(now)]=(addtag[rs(now)]*multag[now]+addtag[now])%p;
    multag[now]=1;
    addtag[now]=0;
}
void mulchange(long long now,long long l,long long r,long long a,long long b,long long c)
{
    if(r<a||l>b)return;

    if(a<=l&&r<=b)
    {
        seg[now]=(seg[now]*c)%p;
        multag[now]=(multag[now]*c)%p;
        addtag[now]=(addtag[now]*c)%p;
        return;
    }
    pushdown(now,l,r);
    long long mid=(l+r)>>1;
    mulchange(ls(now),l,mid,a,b,c);
    mulchange(rs(now),mid+1,r,a,b,c);
    seg[now]=(seg[ls(now)]+seg[rs(now)])%p;
    return;
}
void addchange(long long now,long long l,long long r,long long a,long long b,long long c)
{    
    if(r<a||l>b)return;
    if(l>=a&&r<=b)
    {
        addtag[now]=(addtag[now]+c)%p;
        seg[now]=(seg[now]+c*(r-l+1))%p;
        return;
    }
    pushdown(now,l,r);
    long long mid=(l+r)>>1;
    addchange(ls(now),l,mid,a,b,c);
    addchange(rs(now),mid+1,r,a,b,c);
    seg[now]=(seg[ls(now)]+seg[rs(now)])%p;
    return;
}
long long query(long long now,long long l,long long r,long long a,long long b)
{
    if(r<a||l>b)return 0;
    if(l>=a&&r<=b)return seg[now];
    pushdown(now,l,r);
    long long mid=(l+r)>>1;
    return (query(ls(now),l,mid,a,b)+query(rs(now),mid+1,r,a,b))%p;
}
int main()
{
    n=kd(),m=kd(),p=kd();
    for(register int i=1;i<=n;i++)
    {
        num[i]=kd();
    }
    build(1,1,n);
    for(int i=1;i<=m;i++)
    {
        long long pan=kd();
        long long a=kd(),b=kd();
        if(pan==1)
        {
            long long c=kd();
            mulchange(1,1,n,a,b,c);
        }
        if(pan==2)
        {
            long long c=kd();
            addchange(1,1,n,a,b,c);
        }
        if(pan==3)
        {
            cout<<query(1,1,n,a,b)<<endl;
        }
    }
    return 0;
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!