luogu P3373 模板线段树 2

Posted Excim

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了luogu P3373 模板线段树 2相关的知识,希望对你有一定的参考价值。

原题链接:https://www.luogu.org/problem/show?pid=3373

 

其实也没啥好说的,就是注意一下乘法标记会影响到加法标记

 

#include<cstdio>
void read(int &y)
{
    y=0;char x=getchar();int f=1;
    while(x<0||x>9) {if(x==-) f=-1;x=getchar();}
    while(x>=0&&x<=9) {y=y*10+x-0;x=getchar();}
    y*=f;
}
long long data[400005],fm[400005],fa[400005];
int a[100005],p;
void build(int o,int l,int r)
{
    fm[o]=1;
    if(l==r)
    {
        data[o]=a[l]%p;
        return;
    }
    int mid=(l+r)>>1;
    build(o<<1,l,mid);
    build(o<<1|1,mid+1,r);
    data[o]=(data[o<<1]+data[o<<1|1])%p;
}
void putdown(int o,int l,int r)
{
    int mid=(l+r)>>1;
    data[o<<1]=(data[o<<1]*fm[o]+fa[o]*(mid-l+1))%p;
    data[o<<1|1]=(data[o<<1|1]*fm[o]+fa[o]*(r-mid))%p;
    fm[o<<1]=fm[o<<1]*fm[o]%p;
    fm[o<<1|1]=fm[o<<1|1]*fm[o]%p;
    fa[o<<1]=(fa[o<<1]*fm[o]+fa[o])%p;
    fa[o<<1|1]=(fa[o<<1|1]*fm[o]+fa[o])%p;
    fm[o]=1;
    fa[o]=0;
}
void add(int ll,int rr,int k,int o,int l,int r)
{
    if(ll<=l&&rr>=r)
    {
        data[o]=(data[o]+(r-l+1)*k)%p;
        fa[o]=(fa[o]+k)%p;
        return;
    }
    int mid=(l+r)>>1;
    putdown(o,l,r);
    if(mid>=ll) add(ll,rr,k,o<<1,l,mid);
    if(mid<rr) add(ll,rr,k,o<<1|1,mid+1,r);
    data[o]=(data[o<<1]+data[o<<1|1])%p;
}
void mul(int ll,int rr,int k,int o,int l,int r)
{
    if(ll<=l&&rr>=r)
    {
        data[o]=(data[o]*k)%p;
        fm[o]=(fm[o]*k)%p;
        fa[o]=(fa[o]*k)%p;
        return;
    }
    int mid=(l+r)>>1;
    putdown(o,l,r);
    if(mid>=ll) mul(ll,rr,k,o<<1,l,mid);
    if(mid<rr) mul(ll,rr,k,o<<1|1,mid+1,r);
    data[o]=(data[o<<1]+data[o<<1|1])%p;
}
long long ask(int ll,int rr,int o,int l,int r)
{
    if(ll<=l&&rr>=r) return data[o];
    putdown(o,l,r);
    int mid=(l+r)>>1;
    long long ans=0;
    if(mid>=ll) ans+=ask(ll,rr,o<<1,l,mid);
    if(mid<rr) ans+=ask(ll,rr,o<<1|1,mid+1,r);
    return ans%p;
}
int main()
{
    int n,m,op,l,r,k;
    read(n);read(m);read(p);
    for(int i=1;i<=n;i++) read(a[i]);
    build(1,1,n);
    while(m--)
    {
        read(op);
        if(op==1)
        {
            read(l);read(r);read(k);
            mul(l,r,k,1,1,n);
        }
        if(op==2)
        {
            read(l);read(r);read(k);
            add(l,r,k,1,1,n);
        }
        if(op==3)
        {
            read(l);read(r);
            printf("%lld\n",ask(l,r,1,1,n));
        }
    }
    return 0;
}

 

以上是关于luogu P3373 模板线段树 2的主要内容,如果未能解决你的问题,请参考以下文章

luogu P3373 模板线段树 2

原创洛谷 LUOGU P3373 模板线段树2

luogu P3373 模板线段树 2

Luogu P3373 模板线段树 2

P3373 模板线段树 2区间乘/加 区间查询

P3373 模板线段树 2 (未完待续)