老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成。有长为 NN
的数列,不妨设为 a1,a2,…,aNa1,a2,…,aN
。有如下三种操作形式:把数列中的一段数全部乘一个值;把数列中的一段数全部加一个值;询问数列中的一段数的和,由于答案可能很大,你只需输出这个数模 PP
的值。输入格式第一行两个整数 NN
和 PP
;第二行含有 NN
个非负整数,从左到右依次为 a1,a2,…,aNa1,a2,…,aN
;第三行有一个整数 MM
,表示操作总数;从第四行开始每行描述一个操作,输入的操作有以下三种形式:操作 11
:1 t g c,表示把所有满足 t≤i≤gt≤i≤g
的 aiai
改为 ai×cai×c
;操作 22
:2 t g c,表示把所有满足 t≤i≤gt≤i≤g
的 aiai
改为 ai+cai+c
;操作 33
:3 t g,询问所有满足 t≤i≤gt≤i≤g
的 aiai
的和模 PP
的值。同一行相邻两数之间用一个空格隔开,每行开头和末尾没有多余空格。输出格式对每个操作 33
,按照它在输入中出现的顺序,依次输出一行一个整数表示询问结果。数据范围1≤N,M≤1051≤N,M≤105
,
1≤t≤g≤N1≤t≤g≤N
,
0≤c,ai≤1090≤c,ai≤109
,
1≤P≤1091≤P≤109
输入样例:7 43
1 2 3 4 5 6 7
5
1 2 5 5
3 2 4
2 3 7 9
3 1 3
3 4 7
输出样例:2
35
8
样例解释初始时数列为 {1,2,3,4,5,6,7}{1,2,3,4,5,6,7}
;经过第 11
次操作后,数列为 {1,10,15,20,25,6,7}{1,10,15,20,25,6,7}
;对第 22
次操作,和为 10+15+20=4510+15+20=45
,模 4343
的结果是 22
;经过第 33
次操作后,数列为 {1,10,24,29,34,15,16}{1,10,24,29,34,15,16}
;对第 44
次操作,和为 1+10+24=351+10+24=35
,模 4343
的结果是 3535
;对第 55
次操作,和为 29+34+15+16=9429+34+15+16=94
,模 4343
的结果是 88
。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long LL;
const int N=100010;
int n,m,p;
int w[N];
struct Node{
int l,r;
int sum,add,mul;
}tr[N*4];
void pushup(int u){
tr[u].sum=(tr[u<<1].sum+tr[u<<1|1].sum)%p;
}
void eval(Node &t,int add,int mul){
t.sum=((LL)t.sum*mul+(LL)(t.r-t.l+1)*add)%p;
t.mul=((LL)t.mul*mul)%p;
t.add=((LL)t.add*mul+add)%p;
}
void pushdown(int u){
eval(tr[u<<1],tr[u].add,tr[u].mul);
eval(tr[u<<1|1],tr[u].add,tr[u].mul);
tr[u].add=0,tr[u].mul=1;
}
void build(int u,int l,int r){
if(l==r) tr[u]={l,r,w[r],0,1};
else{
tr[u]={l,r,0,0,1};
int mid=l+r>>1;
build(u<<1,l,mid),build(u<<1|1,mid+1,r);
pushup(u);
}
}
void modify(int u,int l,int r,int add,int mul){
if(tr[u].l>=l && tr[u].r<=r) eval(tr[u],add,mul);
else{
pushdown(u);
int mid=tr[u].l+tr[u].r>>1;
if(l<=mid) modify(u<<1,l,r,add,mul);
if(r>mid) modify(u<<1|1,l,r,add,mul);
pushup(u);
}
}
int query(int u,int l,int r){
if(tr[u].l>=l && tr[u].r<=r) return tr[u].sum;
pushdown(u);
int mid=tr[u].l+tr[u].r>>1;
int sum=0;
if(l<=mid) sum=query(u<<1,l,r);
if(r>mid) sum=(sum+query(u<<1|1,l,r))%p;
return sum;
}
int main(){
scanf("%d%d",&n,&p);
for(int i=1;i<=n;i++) scanf("%d",&w[i]);
build(1,1,n);
scanf("%d",&m);
while(m--){
int t,l,r,d;
scanf("%d%d%d",&t,&l,&r);
if(t==1){
scanf("%d",&d);
modify(1,l,r,0,d);
}
else if(t==2){
scanf("%d",&d);
modify(1,l,r,d,1);
}
else printf("%d\n",query(1,l,r));
}
return 0;
}