【模板】线段树(洛谷P3373)

Description

  如题,已知一个数列,你需要进行下面三种操作:

  1.将某区间每一个数乘上x

  2.将某区间每一个数加上x

  3.求出某区间每一个数的和

Input

  第一行包含三个整数N、M、P,分别表示该数列数字的个数、操作的总个数和模数。

  第二行包含N个用空格分隔的整数,其中第i个数字表示数列第i项的初始值。

  接下来M行每行包含3或4个整数,表示一个操作,具体如下:

  操作1: 格式:1 x y k 含义:将区间[x,y]内每个数乘上k

  操作2: 格式:2 x y k 含义:将区间[x,y]内每个数加上k

  操作3: 格式:3 x y 含义:输出区间[x,y]内每个数的和对P取模所得的结果

Output

  输出包含若干行整数,即为所有操作3的结果。

Solution

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=100000;
long long sum[4*N+10],multag[4*N+10],addtag[4*N+10],a[N+10];
int n,m,Mod,opt,x,y,k;
inline long long read()
{
    long long ans=0,f=1;
    char ch=getchar();
    while (ch<'0' || ch>'9')
    {
        if (ch=='-') f=-1;
        ch=getchar();
    }
    while (ch>='0' && ch<='9')
    {
        ans=ans*10+ch-'0';
        ch=getchar();
    }
    return ans*f;
}
long long mo(long long x,long long y)
{
    return x+y>=Mod?x+y-Mod:x+y;
}
void pushdown(int p,int l,int r)
{
    int mid=(l+r)>>1;
    if (multag[p]!=1)
    {
        sum[p<<1]=sum[p<<1]*multag[p]%Mod;
        sum[p<<1|1]=sum[p<<1|1]*multag[p]%Mod;
        multag[p<<1]=multag[p<<1]*multag[p]%Mod;
        multag[p<<1|1]=multag[p<<1|1]*multag[p]%Mod;
        addtag[p<<1]=addtag[p<<1]*multag[p]%Mod;
        addtag[p<<1|1]=addtag[p<<1|1]*multag[p]%Mod;
        multag[p]=1;
    }
    if (addtag[p])
    {
        sum[p<<1]=mo(sum[p<<1],addtag[p]*(mid-l+1)%Mod);
        sum[p<<1|1]=mo(sum[p<<1|1],addtag[p]*(r-mid)%Mod);
        addtag[p<<1]=mo(addtag[p<<1],addtag[p]);
        addtag[p<<1|1]=mo(addtag[p<<1|1],addtag[p]);
        addtag[p]=0;
    }
}
void build(int p,int l,int r)
{
    if (l==r)
    {
        sum[p]=a[l];
        multag[p]=1,addtag[p]=0;
        return;
    }
    int mid=(l+r)>>1;
    build(p<<1,l,mid);
    build(p<<1|1,mid+1,r);
    sum[p]=mo(sum[p<<1],sum[p<<1|1]);
    multag[p]=1;addtag[p]=0;
}
void modify_mul(int p,int l,int r,int i,int j,long long v)
{
    if (l==i && r==j)
    {
        sum[p]=sum[p]*v%Mod;
        multag[p]=multag[p]*v%Mod;
        addtag[p]=addtag[p]*v%Mod;
        return;
    }
    pushdown(p,l,r);
    int mid=(l+r)>>1;
    if (j<=mid) modify_mul(p<<1,l,mid,i,j,v);
    else if (i>mid) modify_mul(p<<1|1,mid+1,r,i,j,v);
    else
    {
        modify_mul(p<<1,l,mid,i,mid,v);
        modify_mul(p<<1|1,mid+1,r,mid+1,j,v);
    }
    sum[p]=mo(sum[p<<1],sum[p<<1|1]);
}
void modify_add(int p,int l,int r,int i,int j,long long v)
{
    if (l==i && r==j)
    {
        sum[p]=mo(sum[p],v*(r-l+1)%Mod);
        addtag[p]=mo(addtag[p],v);
        return;
    }
    pushdown(p,l,r);
    int mid=(l+r)>>1;
    if (j<=mid) modify_add(p<<1,l,mid,i,j,v);
    else if (i>mid) modify_add(p<<1|1,mid+1,r,i,j,v);
    else
    {
        modify_add(p<<1,l,mid,i,mid,v);
        modify_add(p<<1|1,mid+1,r,mid+1,j,v);
    }
    sum[p]=mo(sum[p<<1],sum[p<<1|1]);
}
long long query(int p,int l,int r,int i,int j)
{
    if (l==i && r==j) return sum[p];
    pushdown(p,l,r);
    int mid=(l+r)>>1;
    if (j<=mid) return query(p<<1,l,mid,i,j);
    else if (i>mid) return query(p<<1|1,mid+1,r,i,j);
    else
    {
        return mo(query(p<<1,l,mid,i,mid),query(p<<1|1,mid+1,r,mid+1,j));
    }
}
int main()
{
    n=read(),m=read(),Mod=read();
    for (int i=1;i<=n;i++) a[i]=read(),a[i]%=Mod;
    build(1,1,n);
    while (m--)
    {
        opt=read();
        if (opt==1)
        {
            x=read(),y=read(),k=read();
            k%=Mod;
            modify_mul(1,1,n,x,y,k);
        }
        if (opt==2)
        {
            x=read(),y=read(),k=read();
            k%=Mod;
            modify_add(1,1,n,x,y,k);
        }
        if (opt==3)
        {
            x=read(),y=read();
            printf("%lld\n",query(1,1,n,x,y));
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Code-Geass/p/9927318.html