题目描述
如题,已知一个数列,你需要进行下面三种操作:
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\n",query(1,L,R));
}
}
}