// Mugurel Ionut Andreica #include #include #include #define USE_BRUTE_FORCE 0 #define LOCAL 0 #define NMAX 131072 #define MOD 1000000007 #define LL long long int sum[2 * NMAX], li[2 * NMAX], ls[2 * NMAX], umult[2 * NMAX], uadd[2 * NMAX], uset[2 * NMAX]; int N, Q, QA, QB, QOP, QUPD, QANS; void PushSet(int node, int v) { umult[node] = 1; uadd[node] = 0; uset[node] = v; sum[node] = ((LL) (ls[node] - li[node] + 1) * (LL) v) % MOD; } void PushMult(int node, int v) { umult[node] = ((LL) umult[node] * (LL) v) % MOD; uadd[node] = ((LL) uadd[node] * (LL) v) % MOD; sum[node] = ((LL) sum[node] * (LL) v) % MOD; } void PushAdd(int node, int v) { uadd[node] += v; if (uadd[node] >= MOD) uadd[node] -= MOD; sum[node] = ((LL) sum[node] + (LL) (ls[node] - li[node] + 1) * (LL) v) % MOD; } // This is the main function for all segment tree operations (updates and queries). // QOP denotes the operation to be performed and [QA,QB] is the interval upon which the operation is applied. void SegTreeOp(int node) { if (QA <= li[node] && ls[node] <= QB) { if (QOP == 1) PushAdd(node, QUPD); else if (QOP == 2) PushMult(node, QUPD); else if (QOP == 3) PushSet(node, QUPD); else { QANS += sum[node]; if (QANS >= MOD) QANS -= MOD; } return; } int lson = node << 1; int rson = lson + 1; if (uset[node] >= 0) { PushSet(lson, uset[node]); PushSet(rson, uset[node]); uset[node] = -1; } if (umult[node] != 1) { PushMult(lson, umult[node]); PushMult(rson, umult[node]); umult[node] = 1; } if (uadd[node] != 0) { PushAdd(lson, uadd[node]); PushAdd(rson, uadd[node]); uadd[node] = 0; } if (QA <= ls[lson]) SegTreeOp(lson); if (QB >= li[rson]) SegTreeOp(rson); if (QOP <= 3) { sum[node] = sum[lson] + sum[rson]; if (sum[node] >= MOD) sum[node] -= MOD; } } int bf[NMAX]; void BruteForce() { int i, ans = 0; for (i = QA; i <= QB; i++) { if (QOP == 1) { bf[i] += QUPD; if (bf[i] >= MOD) bf[i] -= MOD; } else if (QOP == 2) { bf[i] = ((LL) bf[i] * (LL) QUPD) % MOD; } else if (QOP == 3) { bf[i] = QUPD; } else { ans += bf[i]; if (ans >= MOD) ans -= MOD; } } if (QOP == 4 && ans != QANS) { fprintf(stderr, "WA: expected=%d got=%d\n", ans, QANS); exit(1); } } int main() { int T, i; for (i = NMAX; i < 2 * NMAX; i++) li[i] = ls[i] = i - NMAX + 1; for (i = NMAX - 1; i >= 1; i--) { int lson = i << 1; int rson = lson + 1; li[i] = li[lson]; ls[i] = ls[rson]; } T = 1; while (T--) { if (LOCAL) { N = 30000; Q = 100000; } else scanf("%d %d", &N, &Q); memset(sum, 0, sizeof(sum)); memset(uadd, 0, sizeof(uadd)); for (i = 1; i < 2 * NMAX; i++) { umult[i] = 1; uset[i] = -1; } if (USE_BRUTE_FORCE) memset(bf, 0, sizeof(bf)); for (i = 1; i <= N; i++) { if (LOCAL) QUPD = 1 + (rand() % 10000); else scanf("%d", &QUPD); QUPD %= MOD; QA = QB = i; QOP = 1; SegTreeOp(1); if (USE_BRUTE_FORCE) BruteForce(); } while (Q--) { if (LOCAL) QOP = 1 + (rand() % 4); else scanf("%d", &QOP); if (QOP <= 3) { if (LOCAL) { QA = 1 + (rand() % N); QB = QA + (rand() % (N - QA + 1)); QUPD = 1 + (rand() % 10000); } else scanf("%d %d %d", &QA, &QB, &QUPD); QUPD %= MOD; SegTreeOp(1); } else { if (LOCAL) { QA = 1 + (rand() % N); QB = QA + (rand() % (N - QA + 1)); } else scanf("%d %d", &QA, &QB); QANS = 0; SegTreeOp(1); printf("%d\n", QANS); } if (USE_BRUTE_FORCE) BruteForce(); } } return 0; }