因为记笔记是很不好玩的事情……
https://www.luogu.org/recordnew/show/18875922
我写的第一颗线段树,支持单点修改、查询区间和,常数很大。
——2019.5.8晚
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 struct Node{ 5 int l , r; 6 int val; 7 }t[500001 << 3]; 8 int a[500001], n, m; 9 void build(int ind, int l, int r) { 10 if(l == r) { 11 t[ind].l = l; 12 t[ind].r = r; 13 t[ind].val = a[l]; 14 return; 15 } 16 t[ind].l = l; 17 t[ind].r = r; 18 int mid = (l + r) >> 1; 19 build(ind << 1, l, mid); 20 build((ind << 1) + 1, mid + 1, r); 21 t[ind].val = t[ind << 1].val + t[(ind << 1) + 1].val; 22 return; 23 } 24 25 //void search(int ind) { 26 // cout << t[ind].l << "<->" << t[ind].r << '\n'; 27 // if(t[ind << 1].val) search(ind << 1); 28 // if(t[(ind << 1) + 1].val) search((ind << 1) + 1); 29 //} 30 //第一次写, 很好奇地先序遍历了一下 31 32 void updata(int x, int val, int ind) { 33 //cout << t[ind].l << '-' << t[ind].r << '\n'; 34 if(t[ind].l == t[ind].r) { 35 t[ind].val += val; 36 return; 37 } 38 int mid = (t[ind].l + t[ind].r) / 2; 39 if(x > mid) { 40 updata(x, val, (ind << 1) + 1); 41 } 42 else { 43 updata(x, val, ind << 1); 44 } 45 t[ind].val += val; 46 } 47 48 int ask(int x, int y, int ind) { 49 if(t[ind].l == t[ind].r) return t[ind].val; 50 int mid = (t[ind].l + t[ind].r) >> 1; 51 if(x <= mid && y > mid) return ask(x , mid, ind << 1) + ask(mid + 1, y, (ind << 1) + 1); 52 else if(x <= mid && y <= mid) { 53 return ask(x, y, ind << 1); 54 } 55 else return ask(x, y, (ind << 1) + 1); 56 } 57 58 int main() { 59 cin >> n >> m; 60 for(register int i = 1; i <= n; ++i) { 61 scanf("%d", &a[i]); 62 } 63 build(1, 1, n); 64 // search(1); 65 int oper = 0, x = 0, y = 0, k = 0; 66 for(int i = 1; i <= m; ++i) { 67 scanf("%d", &oper); 68 switch(oper) { 69 case 1: 70 scanf("%d%d", &x, &k); 71 updata(x,k,1); 72 break; 73 case 2: 74 scanf("%d%d", &x, &y); 75 cout << ask(x,y,1) << '\n'; 76 break; 77 } 78 } 79 return 0; 80 }
https://www.luogu.org/recordnew/show/18880248
第二颗线段树!支持区间加和、单点查询数值,这次没有超时。
——2019.5.9上午
1 #include<cstdio> 2 #include<iostream> 3 #include<cctype> 4 //对于100%的数据:N<=500000,M<=500000 区间加,单点查询 5 using namespace std; 6 int read() { 7 char c = getchar(); 8 int x = 0, f = 1; 9 while(!isdigit(c)) { 10 if(c == '-') f = -1; 11 c = getchar(); 12 } 13 while(isdigit(c)) { 14 x = x*10 + c - '0'; 15 c = getchar(); 16 } 17 return x * f; 18 } 19 struct Node{ 20 int l, r; 21 int val, tag; 22 }t[500000 << 1 + 1]; 23 int n, m, a[500001]; 24 25 void build(int ind, int left, int right) { 26 if(left == right) { 27 t[ind].l = left; 28 t[ind].r = right; 29 t[ind].val = a[left]; 30 return; 31 } 32 int mid = (left + right) >> 1; 33 t[ind].l = left; 34 t[ind].r = right; 35 build(ind << 1, left, mid); 36 build((ind<<1) + 1, mid + 1, right); 37 t[ind].val = t[ind << 1].val + t[(ind<<1) + 1].val; 38 return; 39 } 40 41 void updata(int left, int right, int value, int ind) { 42 if(left == t[ind].l && right == t[ind].r) { 43 t[ind].tag += value; 44 return; 45 } 46 int mid = (t[ind].l + t[ind].r) >> 1; 47 if(left > mid) updata(left, right, value, (ind << 1) + 1); 48 else 49 if(right < mid+1) updata(left, right, value, ind << 1); 50 else { 51 updata(left, mid, value, ind << 1); 52 updata(mid + 1, right, value, (ind << 1) + 1); 53 } 54 return; 55 } 56 57 int ask(int x, int ind) { 58 if(t[ind].l == t[ind].r) { 59 t[ind].val += t[ind].tag; 60 t[ind].tag = 0; 61 return t[ind].val; 62 } 63 t[ind << 1].tag += t[ind].tag; 64 t[(ind << 1) + 1].tag += t[ind].tag; 65 t[ind].val += t[ind].tag; 66 t[ind].tag = 0; 67 int mid = (t[ind].l + t[ind].r) >> 1; 68 if(x > mid) return ask(x, (ind << 1) + 1); 69 else return ask(x, ind << 1); 70 } 71 72 int main() { 73 n = read(); 74 m = read(); 75 for(int i = 1; i <= n; ++i) { 76 a[i] = read(); 77 } 78 build(1,1,n); 79 int oper, x, y, k; 80 for(int i = 1; i <= m; ++i) { 81 oper = read(); 82 switch(oper) { 83 case 1: 84 x = read(), y = read(), k = read(); 85 updata(x, y, k, 1); break; 86 case 2: 87 x = read(); 88 cout << ask(x,1) << '\n'; 89 break; 90 } 91 } 92 return 0; 93 }
第三颗,支持区间加和,查询区间和,就是卡不过常数去
https://loj.ac/submission/445888
——2019.5.9晚
1 #include<cstdio> 2 #include<iostream> 3 using namespace std; 4 struct Node{ 5 long long l, r; 6 long long val, tag; 7 }t[1000000 << 2 + 1]; 8 long long a[1000001], n, m, oper, x, y, k; 9 10 long long read() { 11 long long x = 0, f = 1; 12 char c = getchar(); 13 while(c < '0' || c > '9') { 14 if(c == '-') f = -f; 15 c = getchar(); 16 } 17 while(c >= '0' && c <= '9') { 18 x = x*10 + c - '0'; 19 c = getchar(); 20 } 21 return x * f; 22 } 23 void build(long long ind, long long left, long long right) { 24 t[ind].l = left, t[ind].r = right; 25 if(left == right) { 26 t[ind].val = a[left]; 27 return; 28 } 29 long long mid = (left + right) >> 1; 30 build(ind << 1, left, mid); 31 build((ind << 1) + 1, mid + 1, right); 32 t[ind].val = t[ind << 1].val + t[(ind << 1) + 1].val; 33 return; 34 } 35 36 void updata(long long ind, long long left, long long right, long long value) { 37 if(left == t[ind].l && right == t[ind].r) { 38 t[ind].tag += value; 39 return; 40 } 41 t[ind].val += (right - left + 1) * value; 42 long long mid = (t[ind].l + t[ind].r) >> 1; 43 if(left > mid) { 44 updata((ind << 1) + 1, left, right, value); 45 } 46 else if(mid >= right) { 47 updata(ind << 1, left, right, value); 48 } 49 else { 50 updata(ind << 1, left, mid, value); 51 updata((ind << 1) + 1, mid + 1, right, value); 52 } 53 } 54 55 long long ask(long long ind, long long left, long long right) { 56 t[ind].val += (t[ind].r - t[ind].l + 1) * t[ind].tag; 57 t[ind << 1].tag += t[ind].tag; 58 t[(ind << 1) + 1].tag += t[ind].tag; 59 t[ind].tag = 0; 60 if(t[ind].l == left && t[ind].r == right) { 61 return t[ind].val; 62 } 63 long long mid = (t[ind].l + t[ind].r) >> 1; 64 if(left > mid) { 65 return ask((ind << 1) + 1, left, right); 66 } 67 else if(mid >= right) { 68 return ask(ind << 1, left, right); 69 } 70 else { 71 return ask(ind << 1, left, mid) + ask((ind << 1) + 1, mid + 1, right); 72 } 73 } 74 int main() { 75 n = read(), m = read(); 76 for(long long i = 1; i <= n; ++i) 77 a[i] = read(); 78 79 build(1, 1, n); 80 81 for(long long i = 1; i <= m; ++i) { 82 oper = read(); 83 switch(oper) { 84 case 1: 85 x = read(), y = read(), k = read(); 86 updata(1, x, y, k); break; 87 case 2: 88 x = read(), y = read(); 89 cout << ask(1, x, y) << '\n'; 90 break; 91 } 92 } 93 return 0; 94 }
今天早上痛定思痛,换一种线段树的写法,做第一颗树栽了的那题
快了不少,这就是第四颗了。
https://www.luogu.org/recordnew/show/18905672 ——5.10 / 2019
1 #include<cstdio> 2 #include<iostream> 3 using namespace std; 4 int t[500000 << 2 + 1], n, m, a[500001], oper, x, y, k; 5 int read() { 6 char c = getchar(); 7 int x = 0, f = 1; 8 while(c < '0' || c > '9') { 9 if(c == '-') f = -1; 10 c = getchar(); 11 } 12 while(c >= '0' && c <= '9') { 13 x = x*10 + c - '0'; 14 c = getchar(); 15 } 16 return x*f; 17 } 18 19 void build(int ind, int l, int r) { 20 if(l == r) { 21 t[ind] = a[l]; 22 return; 23 } 24 int m = (l + r) >> 1; 25 build(ind << 1, l, m); 26 build((ind<<1) + 1, m + 1, r); 27 t[ind] = t[ind << 1] + t[(ind<<1) + 1]; 28 } 29 30 void updata(int ind, int l, int r, int x, int val) { 31 t[ind] += val; 32 if(l == r) return; 33 int m = (l + r) >> 1; 34 if(x > m) updata((ind<<1) + 1, m + 1, r, x, val); 35 else if(x <= m) updata(ind << 1, l, m, x, val); 36 } 37 38 int ask(int l, int r, int s, int e, int ind) { 39 if(l == s && r == e) return t[ind]; 40 int m = (s + e) >> 1; 41 if(l > m) return ask(l, r, m+1, e, (ind<<1) + 1); 42 else if(r <= m) return ask(l, r, s, m, ind << 1); 43 else return ask(l, m, s, m, ind << 1) + ask(m+1, r, m+1, e, (ind<<1) + 1); 44 } 45 46 int main() { 47 n = read(), m = read(); 48 for(int i = 1; i <= n; ++i) 49 a[i] = read(); 50 build(1, 1, n); 51 for(int i = 1; i <= m; ++i) { 52 oper = read(); 53 switch(oper) { 54 case 1: 55 x = read(), k = read(); 56 updata(1, 1, n, x, k); break; 57 case 2: 58 x = read(), y = read(); 59 cout << ask(x, y, 1, n, 1) << '\n'; break; 60 } 61 } 62 return 0; 63 }
2019,5,12:第五颗
通过对线段树的思考明白了冗余信息的计算对速度的拖延。
以下一块代码是第五颗,有优化的余地。
1 #include<cstdio> 2 #include<iostream> 3 using namespace std; 4 struct Node{ 5 long long l, r, mid; 6 long long val, tag; 7 }t[100000 << 3]; 8 long long n, m, a[100001]; 9 long long read() { 10 char c = getchar(); 11 long long x = 0, f = 1; 12 while(c < '0' || c > '9') { 13 if(c == '-') f = -1; 14 c = getchar(); 15 } 16 while(c >= '0' && c <= '9') { 17 x = x * 10 + c - '0'; 18 c = getchar(); 19 } 20 return x * f; 21 } 22 23 inline long long lc(long long k) { 24 return k << 1; 25 } 26 inline long long rc(long long k) { 27 return k << 1 | 1; 28 } 29 30 inline void pushdown(long long ind) { 31 t[lc(ind)].tag += t[ind].tag; 32 t[rc(ind)].tag += t[ind].tag; 33 34 t[lc(ind)].val += t[ind].tag * (t[lc(ind)].r - t[lc(ind)].l + 1); 35 t[rc(ind)].val += t[ind].tag * (t[rc(ind)].r - t[rc(ind)].l + 1); 36 t[ind].tag = 0; 37 } 38 39 inline void pushup(long long ind) { 40 t[ind].val = t[lc(ind)].val + t[rc(ind)].val; 41 } 42 43 44 45 void build(long long i, long long x, long long y) { 46 t[i].l = x, t[i].r = y; 47 t[i].mid = (x + y) >> 1; 48 if(x == y) { 49 t[i].val = a[x]; 50 return; 51 } 52 build(lc(i), x, t[i].mid); 53 build(rc(i), t[i].mid + 1, y); 54 pushup(i); 55 } 56 57 void updata(long long ind, long long x, long long y, long long k) { 58 if(t[ind].tag) pushdown(ind); 59 60 if(t[ind].l == x && t[ind].r == y) { 61 t[ind].val += (y - x + 1) * k; 62 t[ind].tag += k; 63 return; 64 } 65 66 if(y <= t[ind].mid) updata(lc(ind), x, y, k); 67 else 68 if(x > t[ind].mid) updata(rc(ind), x, y, k); 69 else { 70 updata(lc(ind), x, t[ind].mid, k); 71 updata(rc(ind), t[ind].mid + 1, y, k); 72 } 73 74 pushup(ind); 75 } 76 77 long long ask(long long ind, long long x, long long y) { 78 if(t[ind].tag) pushdown(ind); 79 80 if(t[ind].l == x && t[ind].r == y) return t[ind].val; 81 82 if(y <= t[ind].mid) return ask(lc(ind), x, y); 83 else 84 if(x > t[ind].mid) return ask(rc(ind), x, y); 85 else { 86 return ask(lc(ind), x, t[ind].mid) + ask(rc(ind), t[ind].mid + 1, y); 87 } 88 } 89 90 int main() { 91 n = read(), m = read(); 92 for(long long i = 1; i <= n; ++i) 93 a[i] = read(); 94 build(1, 1, n); 95 long long opt, x, y, k; 96 for(long long i = 1; i <= m; ++i) { 97 opt = read(); 98 if(opt == 1) { 99 x = read(), y = read(), k = read(); 100 updata(1, x, y, k); 101 } 102 else { 103 x = read(), y = read(); 104 cout << ask(1, x, y) << '\n'; 105 } 106 } 107 return 0; 108 }
2019.5.17 第n颗, 速度好快啊, define真方便啊。(忽然发现第三颗更快~qwq)
https://www.luogu.org/recordnew/show/19106653
1 #include<iostream> 2 #include<cstdio> 3 using namespace std; 4 #define ls (ind << 1) 5 #define rs ((ind << 1) + 1) 6 #define mid ((l + r) >> 1) 7 long long a[100001], v[100000 << 2], tag[100000 << 2], k; 8 9 inline void pushdown(long long ind, long long l, long long r) { 10 if(l == r) { 11 tag[ind] = 0; 12 return; 13 } 14 15 tag[ls] += tag[ind]; 16 tag[rs] += tag[ind]; 17 18 v[ls] += (mid - l + 1) * tag[ind]; 19 v[rs] += (r - mid) * tag[ind]; 20 21 tag[ind] = 0; 22 } 23 24 void build(long long ind, long long l, long long r) { 25 if(l == r) { 26 v[ind] = a[l]; 27 return; 28 } 29 build(ls, l, mid); 30 build(rs, mid + 1, r); 31 v[ind] = v[ls] + v[rs]; 32 } 33 34 void add(long long ind, long long l, long long r, long long x, long long y) { 35 36 if(tag[ind]) 37 pushdown(ind, l, r); 38 39 if(l == x && r == y) { 40 v[ind] += (r - l + 1) * k; 41 tag[ind] += k; 42 return; 43 } 44 45 if(y <= mid) add(ls, l, mid, x, y); 46 else if(x > mid) add(rs, mid + 1, r, x, y); 47 else { 48 add(ls, l, mid, x, mid); 49 add(rs, mid + 1, r, mid + 1, y); 50 } 51 52 v[ind] = v[ls] + v[rs]; 53 } 54 55 long long ask(long long ind, long long l, long long r, long long x, long long y) { 56 57 58 if(l == x && r == y) { 59 return v[ind]; 60 } 61 62 if(tag[ind]) 63 pushdown(ind, l, r); 64 65 if(y <= mid) return ask(ls, l, mid, x, y); 66 else if(x > mid) return ask(rs, mid + 1, r, x, y); 67 else return ask(ls, l, mid, x, mid) + ask(rs, mid + 1, r, mid + 1, y); 68 } 69 70 int main() { 71 long long n, m; 72 scanf("%lld%lld", &n, &m); 73 for(long long i = 1; i <= n; ++i) 74 scanf("%lld", &a[i]); 75 build(1, 1, n); 76 long long opt, x, y; 77 for(long long i = 1; i <= m; ++i) { 78 scanf("%lld", &opt); 79 if(opt == 2) { 80 scanf("%lld%lld", &x, &y); 81 cout << ask(1, 1, n, x, y) << '\n'; 82 } 83 else { 84 scanf("%lld%lld%lld", &x, &y, &k); 85 add(1, 1, n, x, y); 86 } 87 } 88 return 0; 89 }
2019.5.21
第n+1颗?学会了用指针写线段树。
https://www.luogu.org/recordnew/show/19239222
但是结果很不好
#include<cstdio>
#include<iostream>
using namespace std;
#define mid (l+r >> 1)
const int maxn = 100000;
struct Node{
long long val, tag;
Node *lc, *rc;
};
Node* root;
long long k;
inline void pushdown(Node* &u, int l, int r) {
if(l == r) {
u->tag = 0;
return;
}
u->lc->val += (mid-l+1) * u->tag;
u->rc->val += (r-mid) * u->tag;
u->lc->tag += u->tag;
u->rc->tag += u->tag;
u->tag = 0;
}
void build(Node* &u, int l, int r) {
u = new Node;
if(l == r) {
scanf("%lld", &u->val);
return;
}
build(u->lc, l, mid);
build(u->rc, mid+1, r);
u->val = u->lc->val + u->rc->val;
}
void add(Node* &u, int x, int y, int l, int r) {
if(x == l && y == r) {
u->val += (r-l+1)*k;
u->tag += k;
return;
}
if(y <= mid) add(u->lc, x, y, l, mid);
else
if(x > mid) add(u->rc, x, y, mid+1, r);
else {
add(u->lc, x, mid, l, mid);
add(u->rc, mid+1, y, mid+1, r);
}
u->val = u->lc->val + u->rc->val;
}
long long query(Node* &u, int x, int y, int l, int r) {
if(u->tag) pushdown(u, l, r);
if(l == r) return u->val;
if(y <= mid) return query(u->lc, x, y, l, mid);
if(x > mid) return query(u->rc, x, y, mid+1, r);
return query(u->lc, x, mid, l, mid) + query(u->rc, mid+1, y, mid+1, r);
}
int main() {
int n, m;
scanf("%d%d", &n, &m);
build(root, 1, n);
int opt, x, y;
for(int i = 1; i <= m; ++i) {
scanf("%d", &opt);
if(opt == 1) {
scanf("%d%d%lld", &x, &y, &k);
add(root, x, y, 1, n);
}
else {
scanf("%d%d", &x, &y);
cout << query(root, x, y, 1, n) <<'\n';
}
}
return 0;
}
2019.5.21晚21:46:07
依旧是指针线段树,但是好了太多。
https://www.luogu.org/recordnew/show/19254090
#include<cstdio>
#include<iostream>
using namespace std;
struct Node{
int l, r;
long long val, tag;
Node *lc, *rc;
Node(int x, int y, long long v, long long t, Node* a, Node* b) {
l = x;
r = y;
val = v;
tag = t;
lc = a;
rc = b;
}
};
Node* root;
int opt, x, y;
long long k, a[100001];
Node* build(int l, int r) {
if(l == r) return new Node(l, r, a[l], 0, NULL, NULL);
int mid = (l + r) >> 1;
Node *left = build(l, mid), *right = build(mid+1, r);
return new Node(l, r, left->val + right->val, 0, left, right);
}
inline void pushdown(Node* &u) {
if(u->l == u->r) {
u->tag = 0;
return;
}
int mid = (u->r + u->l) >> 1;
u->lc->val += (mid - u->l + 1) * u->tag;
u->rc->val += (u->r - mid) * u->tag;
u->lc->tag += u->tag;
u->rc->tag += u->tag;
u->tag = 0;
}
void modify(int l, int r, Node* &u) {
if(u->tag) pushdown(u);
if(l == u->l && r == u->r) {
u->val += (r - l + 1) * k;
u->tag += k;
return;
}
int mid = (u->l + u->r) >> 1;
if(r < mid+1) modify(l, r, u->lc);
else if(l > mid) modify(l, r, u->rc);
else {
modify(l, mid, u->lc);
modify(mid+1, r, u->rc);
}
u->val = u->lc->val + u->rc->val;
}
long long query(int l, int r, Node* &u) {
if(u->tag) pushdown(u);
if(l == u->l && r == u->r) return u->val;
int mid = (u->l + u->r) >> 1;
if(r < mid+1) return query(l, r, u->lc);
if(l > mid) return query(l, r, u->rc);
return query(l, mid, u->lc) + query(mid+1, r, u->rc);
}
int main() {
int n, m;
scanf("%d%d", &n, &m);
for(register int i = 1; i <= n; ++i)
scanf("%lld", &a[i]);
root = build(1, n);
for(register int i = 1; i <= m; ++i) {
scanf("%d", &opt);
if(opt == 1) {
scanf("%d%d%lld", &x, &y, &k);
modify(x, y, root);
}
else {
scanf("%d%d", &x, &y);
printf("%lld\n", query(x, y, root));
}
}
return 0;
}
2019.5.22
第n+3颗,入门了?(笑
https://www.luogu.org/recordnew/show/19259419
// luogu-judger-enable-o2
#include<cstdio>
#include<iostream>
using namespace std;
struct Node{
long long val, tag1, tag2;
long long begin, end;
Node *ls, *rs;
Node(long long v, long long b, long long e, Node* l, Node* r) {
val = v, begin = b, end = e, ls = l, rs = r;
tag1 = 0, tag2 = 1;
}
}*root;
long long a[100001], n, m, MOD;
long long k, opt, x, y;
void read(long long &x) {
x = 0;
long long f = 1;
char c = getchar();
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
x = x*10 + c - '0';
c = getchar();
}
x *= f;
}
inline void Pushdown(Node* &u) {
if(u->tag1 == 0 && u->tag2 == 1) return;
if(u->begin == u->end) {
u->tag1 = 0;
u->tag2 = 1;
return;
}
long long k1 = u->tag1%MOD, k2 = u->tag2%MOD;
long long l = u->begin, r = u->end;
long long mid = (l+r)>>1;
u->tag1 = 0, u->tag2 = 1;
u->ls->tag1 = (u->ls->tag1 * k2) % MOD;
u->rs->tag1 = (u->rs->tag1 * k2) % MOD;
u->ls->tag1 = (u->ls->tag1 + k1) % MOD;
u->rs->tag1 = (u->rs->tag1 + k1) % MOD;
u->ls->tag2 = (u->ls->tag2 * k2) % MOD;
u->rs->tag2 = (u->rs->tag2 * k2) % MOD;
u->ls->val = (u->ls->val * k2) % MOD;
u->ls->val = (u->ls->val + k1*(mid-l+1)%MOD ) % MOD;
u->rs->val = (u->rs->val * k2) % MOD;
u->rs->val = (u->rs->val + k1*(r-mid)%MOD ) % MOD;
}
Node* build(long long l, long long r) {
if(l == r) return new Node(a[l], l, r, NULL, NULL);
long long mid = (l+r)>>1;
Node *left = build(l, mid), *right = build(mid+1, r);
return new Node((left->val + right->val) % MOD, l, r, left, right);
}
void Mul_modify(Node* &u, long long l, long long r) {
if(l == u->begin && r == u->end) {
u->val = (u->val % MOD * k % MOD) % MOD;
u->tag1 = (u->tag1 % MOD * k % MOD) % MOD;
u->tag2 = (u->tag2 % MOD * k % MOD) % MOD;
return;
}
Pushdown(u);
long long mid = (u->begin + u->end) >> 1;
if(r < mid+1) Mul_modify(u->ls, l, r);
else if(l > mid) Mul_modify(u->rs, l, r);
else {
Mul_modify(u->ls, l, mid);
Mul_modify(u->rs, mid+1, r);
}
u->val = (u->ls->val % MOD + u->rs->val % MOD) % MOD + MOD;
}
void Add_modify(Node* &u, long long l, long long r) {
if(l == u->begin && r == u->end) {
u->val = (u->val % MOD + (u->end - u->begin + 1) * k % MOD) % MOD;
u->tag1 = (u->tag1 % MOD + k % MOD) % MOD;
return;
}
Pushdown(u);
long long mid = (u->begin + u->end) >> 1;
if(r < mid+1) Add_modify(u->ls, l, r);
else if(l > mid) Add_modify(u->rs, l, r);
else {
Add_modify(u->ls, l, mid);
Add_modify(u->rs, mid+1, r);
}
u->val = (u->ls->val % MOD + u->rs->val % MOD) % MOD;
}
long long query(Node* &u, long long l, long long r) {
if(l == u->begin && r == u->end) return u->val%MOD;
Pushdown(u);
long long mid = (u->begin + u->end) >> 1;
if(r < mid+1) return query(u->ls, l, r)%MOD;
if(l > mid) return query(u->rs, l, r)%MOD;
return query(u->ls, l, mid)%MOD + query(u->rs, mid+1, r)%MOD;
}
int main() {
read(n), read(m), read(MOD);
for(register long long i = 1; i <= n; ++i)
read(a[i]), a[i] %= MOD;
root = build(1, n);
for(register long long i = 1; i <= m; ++i) {
read(opt);
switch(opt) {
case 1:
read(x), read(y), read(k);
Mul_modify(root, x, y); break;
case 2:
read(x), read(y), read(k);
Add_modify(root, x, y); break;
case 3:
read(x), read(y);
cout << (query(root, x, y) % MOD + MOD) % MOD<<'\n';
}
}
return 0;
}