题意:维护一个序列,支持区间同加或同乘一个数、询问区间和。
(x+d)*c=x*c+d*c标记就是这样处理的,剩下的就是注意到处取模了。
#include<cstdio>
#include<cstring>
#include<iostream>
#define LL long long
using namespace std;
const int maxn=100010;
struct node{
int L,R;
LL sum;
LL plu,mul;
} tree[maxn<<2];
int a[maxn],mod,n,m;
void pushup(int p){
tree[p].sum=(tree[p<<1].sum+tree[p<<1|1].sum)%mod;
}
void update1(int p,LL d){
int len=tree[p].R-tree[p].L+1;
tree[p].sum=(tree[p].sum+d*len%mod)%mod;
tree[p].plu=(tree[p].plu+d)%mod;
}
void update2(int p,LL d){
tree[p].sum=(tree[p].sum*d)%mod;
tree[p].plu=(tree[p].plu*d)%mod;
tree[p].mul=(tree[p].mul*d)%mod;
}
void pushdown(int p){
update2(p<<1,tree[p].mul);
update2(p<<1|1,tree[p].mul);
tree[p].mul=1;
update1(p<<1,tree[p].plu);
update1(p<<1|1,tree[p].plu);
tree[p].plu=0;
}
void build(int p,int L,int R){
if(L==R){
tree[p].L=tree[p].R=L;
tree[p].sum=a[L];
tree[p].plu=0;
tree[p].mul=1;
return;
}
int mid=L+R>>1;
build(p<<1,L,mid);
build(p<<1|1,mid+1,R);
tree[p].L=L;
tree[p].R=R;
tree[p].mul=1;
tree[p].plu=0;
pushup(p);
}
void add(int p,int L,int R,int d){
int n_L=tree[p].L;
int n_R=tree[p].R;
if(L<=n_L && n_R<=R){
update1(p,d);
return;
}
pushdown(p);
int mid=n_L+n_R>>1;
if(L<=mid)add(p<<1,L,R,d);
if(mid<R)add(p<<1|1,L,R,d);
pushup(p);
}
void mul(int p,int L,int R,int d){
int n_L=tree[p].L;
int n_R=tree[p].R;
if(L<=n_L && n_R<=R){
update2(p,d);
return;
}
pushdown(p);
int mid=n_L+n_R>>1;
if(L<=mid)mul(p<<1,L,R,d);
if(mid<R)mul(p<<1|1,L,R,d);
pushup(p);
}
int sum(int p,int L,int R){
int n_L=tree[p].L;
int n_R=tree[p].R;
if(L<=n_L && n_R<=R)return tree[p].sum;
pushdown(p);
int mid=n_L+n_R>>1;
LL ret=0;
if(L<=mid)ret=(ret+sum(p<<1,L,R))%mod;
if(mid<R) ret=(ret+sum(p<<1|1,L,R))%mod;
return ret;
}
int main(){
scanf("%d%d",&n,&mod);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
build(1,1,n);
scanf("%d",&m);
for(int i=1;i<=m;i++){
int fg,L,R,d;
scanf("%d",&fg);
switch(fg){
case 1:{
scanf("%d%d%d",&L,&R,&d);
mul(1,L,R,d);
break;
}
case 2:{
scanf("%d%d%d",&L,&R,&d);
add(1,L,R,d);
break;
}
case 3:{
scanf("%d%d",&L,&R);
printf("%d\n",sum(1,L,R));
break;
}
}
}
}