【题目链接】
【算法】
线段树
注意标记下传
【代码】
#include<bits/stdc++.h>
using namespace std;
#define MAXN 500000
typedef long long LL;
struct SegTreeNode {
LL l,r,sum,lazya,lazyb;
}tree[MAXN+10];
LL i,N,P,Q,l,r,x,opt;
LL a[MAXN+10];
template <typename T> void read(T &x) {
LL f=1; char c = getchar(); x=0;
for (; !isdigit(c); c = getchar()) { if (c=='-') f=-1; }
for (; isdigit(c); c = getchar()) x=x*10+c-'0';
x*=f;
}
inline void write(LL x) {
if (x < 0) {
putchar('-');
x = -x;
}
if (x / 10 > 0) write(x/10);
putchar(x%10+'0');
}
inline void pushup(LL index) {
tree[index].sum = (tree[index*2].sum + tree[index*2+1].sum) % P;
}
inline void pushdown(LL index) {
tree[index*2].sum = (tree[index*2].sum * tree[index].lazya + tree[index].lazyb * (tree[index*2].r - tree[index*2].l + 1)) % P;
tree[index*2+1].sum = (tree[index*2+1].sum * tree[index].lazya + tree[index].lazyb * (tree[index*2+1].r - tree[index*2+1].l + 1)) % P;
tree[index*2].lazya = (tree[index*2].lazya * tree[index].lazya) % P;
tree[index*2+1].lazya = (tree[index*2+1].lazya * tree[index].lazya) % P;
tree[index*2].lazyb = (tree[index*2].lazyb * tree[index].lazya + tree[index].lazyb) % P;
tree[index*2+1].lazyb = (tree[index*2+1].lazyb * tree[index].lazya + tree[index].lazyb) % P;
tree[index].lazya = 1; tree[index].lazyb = 0;
}
inline void build(LL index,LL l,LL r) {
LL mid;
tree[index].l = l;
tree[index].r = r;
tree[index].lazya = 1;
if (l == r) tree[index].sum = a[l] % P;
else {
mid = (l + r) >> 1;
build(index*2,l,mid);
build(index*2+1,mid+1,r);
pushup(index);
}
}
inline void changea(int index,int l,int r,int x) {
LL mid;
pushdown(index);
if ((tree[index].l == l) && (tree[index].r == r)) {
tree[index].sum = tree[index].sum * x % P;
tree[index].lazya = (tree[index].lazya * x) % P;
tree[index].lazyb = (tree[index].lazyb * x) % P;
}else {
if (tree[index].l == tree[index].r) return;
mid = (tree[index].l + tree[index].r) >> 1;
if (r <= mid) changea(index*2,l,r,x);
else if (l >= mid + 1) changea(index*2+1,l,r,x);
else {
changea(index*2,l,mid,x);
changea(index*2+1,mid+1,r,x);
}
pushup(index);
}
}
inline void changeb(LL index,LL l,LL r,LL x) {
LL mid;
pushdown(index);
if ((tree[index].l == l) && (tree[index].r == r)) {
tree[index].sum = (tree[index].sum + x * (tree[index].r - tree[index].l + 1)) % P;
tree[index].lazyb = (tree[index].lazyb + x) % P;
}else {
if (tree[index].l == tree[index].r) return;
mid = (tree[index].l + tree[index].r) >> 1;
if (r <= mid) changeb(index*2,l,r,x);
else if (l >= mid + 1) changeb(index*2+1,l,r,x);
else {
if (tree[index].l == tree[index].r) return;
changeb(index*2,l,mid,x);
changeb(index*2+1,mid+1,r,x);
}
pushup(index);
}
}
inline LL query(LL index,LL l,LL r) {
LL mid;
pushdown(index);
if ((tree[index].l == l) && (tree[index].r == r)) return tree[index].sum;
else {
if (tree[index].l == tree[index].r) return 0;
mid = (tree[index].l + tree[index].r) >> 1;
if (r <= mid) return query(index*2,l,r);
else if (l >= mid + 1) return query(index*2+1,l,r);
else return (query(index*2,l,mid) + query(index*2+1,mid+1,r)) % P;
}
}
int main() {
read(N); read(P);
for (i = 1; i <= N; i++) read(a[i]);
build(1,1,N);
read(Q);
while (Q--) {
read(opt);
if (opt == 1) {
read(l); read(r); read(x);
changea(1,l,r,x);
}else if (opt == 2) {
read(l); read(r); read(x);
changeb(1,l,r,x);
}else {
read(l); read(r);
write(query(1,l,r));
puts("");
}
}
return 0;
}