线段树(二)

题目描述

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

  • 将某区间每一个数乘上 xx

  • 将某区间每一个数加上 xx

  • 求出某区间每一个数的和

输入格式

第一行包含三个整数 n,m,pn,m,p,分别表示该数列数字的个数、操作的总个数和模数。

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

接下来 mm 行每行包含若干个整数,表示一个操作,具体如下:

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

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

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

输出格式

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

输入输出样例

in:

5 5 38
1 5 4 2 3
2 1 4 1
3 2 5
1 2 4 2
2 3 5 5
3 1 4

out:

17

2

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int n,m,a[1000005],mod;
struct node
{
    ll sum,l,r,mu,add;
} t[1000005];
ll read()
{
    ll x=0;
    char ch=getchar();
    while(ch<'0'||ch>'9')ch=getchar();
    while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    return x;
}
void build(ll p,ll l,ll r)
{
    t[p].l=l,t[p].r=r;
    t[p].mu=1;
    if(l==r)
    {
        t[p].sum=a[l]%mod;
        return ;
    }
    ll mid=(l+r)>>1;
    build(p*2,l,mid);
    build(p*2+1,mid+1,r);
    t[p].sum=(t[p*2].sum+t[p*2+1].sum)%mod;
}
void spread(ll p)
{
    t[p*2].sum=(ll)(t[p].mu*t[p*2].sum+((t[p*2].r-t[p*2].l+1)*t[p].add)%mod)%mod;
    t[p*2+1].sum=(ll)(t[p].mu*t[p*2+1].sum+(t[p].add*(t[p*2+1].r-t[p*2+1].l+1))%mod)%mod;//add已经乘过mu啦

    t[p*2].mu=(ll)(t[p*2].mu*t[p].mu)%mod;
    t[p*2+1].mu=(ll)(t[p*2+1].mu*t[p].mu)%mod;

    t[p*2].add=(ll)(t[p*2].add*t[p].mu+t[p].add)%mod;
    t[p*2+1].add=(ll)(t[p*2+1].add*t[p].mu+t[p].add)%mod;

    t[p].mu=1,t[p].add=0;
}
void add(ll p,ll l,ll r,ll k)
{
    if(t[p].l>=l&&t[p].r<=r)
    {
        t[p].add=(t[p].add+k)%mod;
        t[p].sum=(ll)(t[p].sum+k*(t[p].r-t[p].l+1))%mod;//只要加上增加的就好
        return ;
    }
    spread(p);
    t[p].sum=(t[p*2].sum+t[p*2+1].sum)%mod;
    ll mid=(t[p].l+t[p].r)>>1;
    if(l<=mid)add(p*2,l,r,k);
    if(mid<r)add(p*2+1,l,r,k);
    t[p].sum=(t[p*2].sum+t[p*2+1].sum)%mod;

}
void mu(ll p,ll l,ll r,ll k)
{
    if(t[p].l>=l&&t[p].r<=r)
    {
        t[p].add=(t[p].add*k)%mod;//比较重要的一步,add要在这里乘上k,因为后面可能要加其他的数而那些数其实是不用乘k的
        t[p].mu=(t[p].mu*k)%mod;
        t[p].sum=(t[p].sum*k)%mod;
        return ;
    }
    spread(p);
    t[p].sum=t[p*2].sum+t[p*2+1].sum;
    ll mid=(t[p].l+t[p].r)>>1;
    if(l<=mid)mu(p*2,l,r,k);
    if(mid<r)mu(p*2+1,l,r,k);
    t[p].sum=(t[p*2].sum+t[p*2+1].sum)%mod;
}
ll ask(ll p,ll l,ll r)
{
    if(t[p].l>=l&&t[p].r<=r)
    {
        return t[p].sum;
    }
    spread(p);
    ll val=0;
    ll mid=(t[p].l+t[p].r)>>1;
    if(l<=mid)val=(val+ask(p*2,l,r))%mod;
    if(mid<r)val=(val+ask(p*2+1,l,r))%mod;
    return val;
}
int main()
{
    cin>>n>>m>>mod;
    for(int i=1; i<=n; i++)
    {
        a[i]=read();
    }
    build(1,1,n);
    for(int i=1; i<=m; i++)
    {
        int ty=read();
        if(ty==1)
        {
            ll cn=read(),cm=read(),cw=read();
            mu(1,cn,cm,cw);
        }
        else if(ty==2)
        {
            ll cn=read(),cm=read(),cw=read();
            add(1,cn,cm,cw);
        }
        else
        {
            ll cn=read(),cm=read();
            cout<<ask(1,cn,cm)<<endl;
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/iloveysm/p/12385944.html