[Luogu] 线段树 2
https://www.luogu.org/problemnew/show/P3373
双懒标记下放
先乘后加
#include <bits/stdc++.h> using namespace std; const int N = 1e5 + 10; #define LL long long #define lson jd << 1 #define rson jd << 1 | 1 LL w[N << 2], size[N << 2], fadd[N << 2], fmul[N << 2], Answer; int n, Ty, Mod; #define gc getchar() inline int read() { int x = 0; char c = gc; while(c < '0' || c > '9') c = gc; while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = gc; return x; } void Build_tree(int l, int r, int jd) { size[jd] = (r - l + 1); fmul[jd] = 1; if(l == r) {w[jd] = read(); w[jd] %= Mod; return ;} int mid = (l + r) >> 1; Build_tree(l, mid, lson); Build_tree(mid + 1, r, rson); w[jd] = (w[lson] + w[rson]) % Mod; } void Down(int jd) { if(!fadd[jd] && fmul[jd] == 1) return ; w[lson] = w[lson] * fmul[jd] % Mod; w[rson] = w[rson] * fmul[jd] % Mod; w[lson] = w[lson] + fadd[jd] * size[lson] % Mod; w[rson] = w[rson] + fadd[jd] * size[rson] % Mod; fadd[lson] = (fadd[lson] * fmul[jd] + fadd[jd]) % Mod; fadd[rson] = (fadd[rson] * fmul[jd] + fadd[jd]) % Mod; fmul[lson] = fmul[lson] * fmul[jd] % Mod; fmul[rson] = fmul[rson] * fmul[jd] % Mod; fadd[jd] = 0; fmul[jd] = 1; } void Sec_G_mul(int l, int r, int jd, int x, int y, int imp) { if(x <= l && r <= y) { w[jd] = (w[jd] * imp) % Mod; fmul[jd] = (fmul[jd] * imp) % Mod; fadd[jd] = (fadd[jd] * imp) % Mod; return ; } Down(jd); int mid = (l + r) >> 1; if(x <= mid) Sec_G_mul(l, mid, lson, x, y, imp); if(y > mid) Sec_G_mul(mid + 1, r, rson, x, y, imp); w[jd] = (w[lson] + w[rson]) % Mod; } void Sec_G_add(int l, int r, int jd, int x, int y, int k) { if(x <= l && r <= y) { w[jd] = (w[jd] + size[jd] * k) % Mod; fadd[jd] = (fadd[jd] + k) % Mod; return ; } Down(jd); int mid = (l + r) >> 1; if(x <= mid) Sec_G_add(l, mid, lson, x, y, k); if(y > mid) Sec_G_add(mid + 1, r, rson, x, y, k); w[jd] = (w[lson] + w[rson]) % Mod; } void Sec_A(int l, int r, int jd, int x, int y) { if(x <= l && r <= y) { Answer += w[jd]; if(Answer >= Mod) Answer %= Mod; return ; } Down(jd); int mid = (l + r) >> 1; if(x <= mid) Sec_A(l, mid, lson, x, y); if(y > mid) Sec_A(mid + 1, r, rson, x, y); } int main() { n = read(); Ty = read(); Mod = read(); Build_tree(1, n, 1); while(Ty --) { int opt = read(); if(opt == 1) { int x = read(), y = read(), k = read(); k %= Mod; Sec_G_mul(1, n, 1, x, y, k); } else if(opt == 2) { int x = read(), y = read(), k = read(); k %= Mod; Sec_G_add(1, n, 1, x, y, k); } else { int x = read(), y = read(); Answer = 0; Sec_A(1, n, 1, x, y); cout << Answer << endl; } } return 0; } /* 5 5 38 1 5 4 2 3 2 1 4 1 3 2 5 1 2 4 2 2 3 5 5 3 1 4 */
乘法标记下放的时候,加法标记也应该进行改变
这样的话,在标记下放时,先放乘法后放加法。