题目描述
老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成。
有长为N的数列,不妨设为a1,a2,…,aN 。有如下三种操作形式:
(1)把数列中的一段数全部乘一个值;
(2)把数列中的一段数全部加一个值;
(3)询问数列中的一段数的和
由于答案可能很大,你只需输出这个数模P的值。
输入
第一行两个整数N和P(1≤P≤1000000000)。
第二行含有N个非负整数,从左到右依次为a1,a2,…,aN, (0≤ai≤1000000000,1≤i≤N)。
第三行有一个整数M,表示操作总数。
从第四行开始每行描述一个操作,输入的操作有以下三种形式:
操作1:“1 t g c”(不含双引号)。表示把所有满足t≤i≤g的ai改为ai×c (1≤t≤g≤N,0≤c≤1000000000)。
操作2:“2 t g c”(不含双引号)。表示把所有满足t≤i≤g的ai改为ai+c (1≤t≤g≤N,0≤c≤1000000000)。
操作3:“3 t g”(不含双引号)。询问所有满足t≤i≤g的ai的和模P的值 (1≤t≤g≤N)。 同一行相邻两数之间用一个空格隔开,每行开头和末尾没有多余空格。
输出
对每个操作3,按照它在输入中出现的顺序,依次输出一行一个整数表示询问结果。
样例输入
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次操作后,数列为(1,10,15,20,25,6,7)。
对第2次操作,和为10+15+20=45,模43的结果是2。
经过第3次操作后,数列为(1,10,24,29,34,15,16}
对第4次操作,和为1+10+24=35,模43的结果是35。
对第5次操作,和为29+34+15+16=94,模43的结果是8。
测试数据规模如下表所示
#include<cstdio>
#define posl pos<<1
#define posr pos<<1|1
using namespace std;
typedef long long LL;
const int N=1e5+10;
struct node{
LL sum, add, mul; int l, r;
int len(){ return r-l+1; }
}tree[N<<2];
int T, n, ord, t, g;
LL p, c;
void Pushup( int pos ){
tree[pos].sum=(tree[posl].sum+tree[posr].sum)%p;
}
void Pushdown( int pos ){
tree[posl].mul=tree[posl].mul*tree[pos].mul%p;
tree[posr].mul=tree[posr].mul*tree[pos].mul%p;
tree[posl].sum=tree[posl].sum*tree[pos].mul%p;
tree[posr].sum=tree[posr].sum*tree[pos].mul%p;
tree[posl].add=( tree[posl].add*tree[pos].mul%p+tree[pos].add )%p;
tree[posr].add=( tree[posr].add*tree[pos].mul%p+tree[pos].add )%p;
tree[posl].sum=( tree[posl].sum+tree[pos].add*tree[posl].len()%p )%p;
tree[posr].sum=( tree[posr].sum+tree[pos].add*tree[posr].len()%p )%p;
tree[pos].add=0LL; tree[pos].mul=1LL;
}
void Build( int l, int r, int pos ){
tree[pos].l=l; tree[pos].r=r;
tree[pos].add=0LL; tree[pos].mul=1LL;
if( l==r ){
scanf( "%lld", &tree[pos].sum );
return;
}
int mid=(l+r)>>1;
Build( l, mid, posl );
Build( mid+1, r, posr );
Pushup( pos );
}
void Change( int l, int r, int pos, LL val, bool flag ){
if( tree[pos].r<l || r<tree[pos].l ) return;
if( l<=tree[pos].l && tree[pos].r<=r ){
if( flag ){
tree[pos].mul=tree[pos].mul*val%p;
tree[pos].add=tree[pos].add*val%p;
tree[pos].sum=tree[pos].sum*val%p;
}
else{
tree[pos].add=( tree[pos].add+val )%p;
tree[pos].sum=( tree[pos].sum+val*tree[pos].len() )%p;
}
return;
}
Pushdown( pos );
Change( l, r, posl, val, flag );
Change( l, r, posr, val, flag );
Pushup( pos );
}
LL Sum( int l, int r, int pos ){
if( tree[pos].r<l || r<tree[pos].l ) return 0;
if( l<=tree[pos].l && tree[pos].r<=r ) return tree[pos].sum;
Pushdown( pos );
return ( Sum( l, r, posl )+Sum( l, r, posr ) )%p;
}
int main() {
scanf( "%d%lld", &n, &p );
Build( 1, n, 1 );
for( scanf("%d",&T); T; T-- ) {
scanf( "%d%d%d", &ord, &t, &g );
if(ord!=3) {
scanf( "%lld", &c );
if( ord==1 ) Change( t, g, 1, c, 1 );
else if( ord==2 ) Change( t, g, 1, c, 0 );
}
else printf( "%lld\n", Sum( t, g, 1 ) );
}
}