1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114
| #include <iostream> #include <cstring> #include <cstdio>
#define FILE_IN(__fname) freopen(__fname, "r", stdin) #define FILE_OUT(__fname) freopen(__fname, "w", stdout) #define rep(a,s,t,i) for (int a = s; a <= t; a += i) #define repp(a,s,t,i) for (int a = s; a < t; a += i) #define countdown(s) while (s --> 0) #define IMPROVE_IO() std::ios::sync_with_stdio(false)
using std::cin; using std::cout; using std::endl;
const int MAXN = 200000 + 10;
int getint() { int x; scanf("%d", &x); return x; } long long int getll() { long long int x; scanf("%lld", &x); return x; }
int n, CH, m; long long int a[MAXN / 2];
struct SegmentTree { long long int sum[MAXN << 2]; long long int mul[MAXN << 2], add[MAXN << 2]; #define lc(x) ((x << 1)) #define rc(x) ((x << 1 | 1)) SegmentTree() { memset(sum, 0, sizeof sum); memset(mul, 1, sizeof mul); memset(add, 0, sizeof add); } void PushTag(int root, int l, int r) { if (mul[root] == 1 && add[root] == 0) return; if (l != r) { mul[lc(root)] = mul[lc(root)] * mul[root] % CH; mul[rc(root)] = mul[rc(root)] * mul[root] % CH; add[lc(root)] = (add[lc(root)] * mul[root] % CH + add[root]) % CH; add[rc(root)] = (add[rc(root)] * mul[root] % CH + add[root]) % CH; } sum[root] = (sum[root] * mul[root] % CH + add[root] * (r - l + 1) % CH) % CH; mul[root] = 1; add[root] = 0; } void buildTree(int root, int l, int r, long long int *seq) { mul[root] = 1; add[root] = 0; if (l == r) { sum[root] = seq[l]; return; } int mid = (l + r) >> 1; buildTree(lc(root), l, mid, seq); buildTree(rc(root), mid + 1, r, seq); sum[root] = (sum[lc(root)] + sum[rc(root)]) % CH; } long long int Query(int root, int l, int r, int ll, int rr) { PushTag(root, l, r); if (ll <= l && r <= rr) return sum[root]; long long int ret = 0; int mid = (l + r) >> 1; if (ll <= mid) ret = (ret + Query(lc(root), l, mid, ll, rr)) % CH; if (mid + 1 <= rr) ret = (ret + Query(rc(root), mid + 1, r, ll, rr)) % CH; return ret; } void Modify(int method, int root, int l, int r, int ll, int rr, long long int k) { PushTag(root, l, r); if (ll <= l && r <= rr) { if (method == 1) { mul[root] = mul[root] * k % CH; add[root] = add[root] * k % CH; } else { add[root] = (add[root] + k) % CH; } return; } int mid = (l + r) >> 1; if (ll <= mid) Modify(method, lc(root), l, mid, ll, rr, k); if (mid + 1 <= rr) Modify(method, rc(root), mid + 1, r, ll, rr, k); PushTag(lc(root), l, mid); PushTag(rc(root), mid + 1, r); sum[root] = (sum[lc(root)] + sum[rc(root)]) % CH; } } Tree;
int main() { n = getint(); CH = getint(); rep (i, 1, n, 1) a[i] = getint(); Tree.buildTree(1, 1, n, a); m = getint(); countdown (m) { int op = getint(); int l = getint(); int r = getint(); switch (op) { case 1: { long long int k = getll(); Tree.Modify(1, 1, 1, n, l, r, k); break; } case 2: { long long int k = getll(); Tree.Modify(2, 1, 1, n, l, r, k); break; } case 3: { printf("%lld\n", Tree.Query(1, 1, n, l, r)); break; } } } return 0; }
|