线段树模板二

题目描述

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

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

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

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

输入格式

第一行包含三个整数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取模所得的结果

输出格式

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

输入输出样例

输入 #1
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
输出 #1
17
2
#include<bits/stdc++.h>
typedef long long ll;
using namespace std;
const int maxn=2e5+9;
struct tree{
    int l,r;
    ll sum,add,mul;
}a[maxn<<2];
ll s[maxn],p;
void update(int k)
{
    a[k].sum=(a[k<<1].sum+a[k<<1|1].sum)%p;
}
void build(int k,int l,int r)
{
    a[k].l=l,a[k].r=r;
    a[k].add=0;
    a[k].mul=1;
    if(l==r)
    {
        a[k].sum=s[l];return;
    }
    int mid=(l+r)>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r);
    update(k);
}
void pushdown(int k)
{
    if(a[k].l==a[k].r)
    {
        a[k].add=0;
        a[k].mul=1;
        return;
    }
    int mid=(a[k].l+a[k].r)>>1;
    a[k<<1].sum=(a[k<<1].sum*a[k].mul+a[k].add*(mid-a[k].l+1))%p;
    a[k<<1|1].sum=(a[k<<1|1].sum*a[k].mul+a[k].add*(a[k].r-mid))%p;
    a[k<<1].add=(a[k<<1].add*a[k].mul+a[k].add)%p;
    a[k<<1|1].add=(a[k<<1|1].add*a[k].mul+a[k].add)%p;
    a[k<<1].mul=(a[k<<1].mul*a[k].mul)%p;
    a[k<<1|1].mul=(a[k<<1|1].mul*a[k].mul)%p;
    a[k].add=0;
    a[k].mul=1;
    return;
}
void changeplus(int k,int l,int r,int x)
{
//    cout<<a[k].sum<<"??"<<endl;
    if(a[k].l>r||a[k].r<l)return;
    if(l<=a[k].l&&r>=a[k].r)
    {
        a[k].sum=(a[k].sum+x*(a[k].r-a[k].l+1))%p;
        a[k].add=(a[k].add+x)%p;
        return;
    }
    pushdown(k);
    int mid=(a[k].l+a[k].r)>>1;
//    if(l<=mid)
    changeplus(k<<1,l,r,x);
//    if(r>mid)
    changeplus(k<<1|1,l,r,x);
    update(k);
    return;
}
void changemul(int k,int l,int r,int x)
{
//    cout<<a[k].sum<<"!!"<<endl;
    if(a[k].l>r||a[k].r<l)return;
    if(l<=a[k].l&&r>=a[k].r)
    {
        a[k].sum=(a[k].sum*x)%p;
        a[k].mul=(a[k].mul*x)%p;
        a[k].add=(a[k].add*x)%p;
        return;
    }
    pushdown(k);
    int mid=(a[k].l+a[k].r)>>1;
//    if(l<=mid)
    changemul(k<<1,l,r,x);
//    if(r>mid)
    changemul(k<<1|1,l,r,x);
    update(k);
    return;
}
ll query(int k,int l,int r)
{
    if(r<a[k].l||l>a[k].r)return 0;
    pushdown(k);
    if(l<=a[k].l&&r>=a[k].r)
    {
        return a[k].sum;
    }
    int mid=(a[k].l+a[k].r)>>1;
    ll ans=0;
//    if(l<=mid)
    ans=(ans+query(k<<1,l,r))%p;
//    if(r>mid)
    ans=(ans+query(k<<1|1,l,r))%p;
    return ans;
}
int main()
{
    int n,m,i;
    scanf("%d%d%lld",&n,&m,&p);
    for(i=1;i<=n;i++)
    scanf("%lld",&s[i]);
    build(1,1,n);
    while(m--)
    {
        int opt,L,R;
        ll x;
        scanf("%d",&opt);
        if(opt==1)
        {
            scanf("%d%d%lld",&L,&R,&x);
            changemul(1,L,R,x);
        }
        if(opt==2)
        {
            scanf("%d%d%lld",&L,&R,&x);
            changeplus(1,L,R,x);
        }
        if(opt==3)
        {
            scanf("%d%d",&L,&R);
            printf("%lld
",query(1,L,R));
        }
    }
}
欢迎加我qq1165750856一起玩呀~
原文地址:https://www.cnblogs.com/HHHEN/p/11724442.html