题目描述
如题,已知一个数列,你需要进行下面三种操作:
- 将某区间每一个数乘上 x;
- 将某区间每一个数加上 x;
- 求出某区间每一个数的和。
输入格式
第一行包含三个整数 n,q,m,分别表示该数列数字的个数、操作的总个数和模数。
第二行包含 n 个用空格分隔的整数,其中第 i 个数字表示数列第 i 项的初始值。
接下来 q 行每行包含若干个整数,表示一个操作,具体如下:
操作 1: 格式:1 x y k
含义:将区间 [x,y] 内每个数乘上 k
操作 2: 格式:2 x y k
含义:将区间 [x,y] 内每个数加上 k
操作 3: 格式:3 x y
含义:输出区间 [x,y] 内每个数的和对 m 取模所得的结果
输出格式
输出包含若干行整数,即为所有操作 33 的结果。
输入输出样例
输入 #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
说明/提示
【数据范围】
对于 30%30% 的数据:n≤8,q≤10。
对于 70%70% 的数据:n≤10^3,q≤10^4。
对于 100%100% 的数据:1≤n≤10^5,1≤q≤10^5。
除样例外,m=571373。
(数据已经过加强 ^_^)
样例说明:
故输出应为 1717、22(40 mod 38=240mod38=2)。
思路:
本题关键是如何处理乘和加的关系,很自然的想到是确定乘和加的先后顺序,但是可以通过乘法分配率将加法与乘法合并。(代码太长了,很容易错,我错了好多次/(ㄒoㄒ)/~~)
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
struct node{
int l,r;
int da;
int lz;
int lz1;
};
node t[400005];
int a[100005];
int n,m,mod;
void push_down(int i)
{
if(t[i].lz!=0){
t[i*2].lz=(t[i*2].lz+t[i].lz)%mod;
t[i*2+1].lz=(t[i*2+1].lz+t[i].lz)%mod;
int mid=(t[i].l+t[i].r)/2;
t[i*2].da=(t[i*2].da+t[i].lz*(mid-t[i*2].l+1))%mod;
t[i*2+1].da=(t[i*2+1].da+t[i].lz*(t[i*2+1].r-mid))%mod;
t[i].lz=0;
}
return ;
}
void push_down1(int i)
{
if(t[i].lz1!=1){
t[i*2].lz1=(t[i*2].lz1*t[i].lz1)%mod;
t[i*2+1].lz1=(t[i*2+1].lz1*t[i].lz1)%mod;
t[i*2].lz=(t[i*2].lz*t[i].lz1)%mod;
t[i*2+1].lz=(t[i*2+1].lz*t[i].lz1)%mod;
t[i*2].da=(t[i].lz1*t[i*2].da)%mod;
t[i*2+1].da=(t[i].lz1*t[i*2+1].da)%mod;
t[i].lz1=1;
}
return ;
}
void build(int l,int r,int pot){
t[pot].l=l;
t[pot].r=r;
t[pot].lz=0;
t[pot].lz1=1;
if(l==r){
t[pot].da=a[l]%mod;
return ;
}
int mid=(l+r)/2;
build(l,mid,pot*2);
build(mid+1,r,pot*2+1);
t[pot].da=(t[pot*2].da+t[pot*2+1].da)%mod;
return ;
}
void updata(int l,int r,int k,int pot){
if(l<=t[pot].l&&t[pot].r<=r){
t[pot].da=(t[pot].da+k*(t[pot].r-t[pot].l+1)%mod)%mod;
t[pot].lz=(t[pot].lz+k)%mod;
return ;
}
push_down1(pot);
push_down(pot);
if(t[pot*2].r>=l){
updata(l,r,k,pot*2);
}
if(t[pot*2+1].l<=r){
updata(l,r,k,pot*2+1);
}
t[pot].da=(t[pot*2].da+t[pot*2+1].da)%mod;
}
void updata1(int l,int r,int k,int pot){
if(l<=t[pot].l&&t[pot].r<=r){
t[pot].da=(k*t[pot].da)%mod;
t[pot].lz1=(t[pot].lz1*k)%mod;
t[pot].lz=(t[pot].lz*k)%mod;
return ;
}
push_down1(pot);
push_down(pot);
if(t[pot*2].r>=l){
updata1(l,r,k,pot*2);
}
if(t[pot*2+1].l<=r){
updata1(l,r,k,pot*2+1);
}
t[pot].da=(t[pot*2].da+t[pot*2+1].da)%mod;
}
int search(int i,int l,int r){
if(t[i].l>=l && t[i].r<=r)
return t[i].da%mod;
if(t[i].r<l || t[i].l>r) return 0;
push_down1(i);
push_down(i);
int s=0;
if(t[i*2].r>=l) s=(s+search(i*2,l,r))%mod;
if(t[i*2+1].l<=r) s=(s+search(i*2+1,l,r))%mod;
return s;
}
signed main(){
scanf("%lld%lld%lld", &n, &m, &mod);
for(int i=1;i<=n;i++)
scanf("%lld", &a[i]);
build(1,n,1);
while(m--){
int op;
int x,y;
long long k;
scanf("%lld", &op);
if(op==1){
scanf("%lld%lld%lld", &x, &y, &k);
updata1(x,y,k,1);
}
else if(op==2){
scanf("%lld%lld%lld", &x, &y, &k);
updata(x,y,k,1);
}else {
scanf("%lld%lld", &x, &y);
printf("%lld\n",search(1,x,y)%mod);
}
}
return 0;
}