線段樹模板(區間加/乘)
阿新 • • 發佈:2018-12-03
https://www.luogu.org/problemnew/show/P3373
如題,已知一個數列,你需要進行下面三種操作:
1.將某區間每一個數乘上x
2.將某區間每一個數加上x
3.求出某區間每一個數的和
#include<bits/stdc++.h> #optimaze using namespace std; typedef long long ll; const int maxn = 100000 + 5; ll tre[maxn << 2], lzyadd[maxn << 2], lzymup[maxn << 2]; int x, n, m, p; void push_up(int rt) { tre[rt] = (tre[rt << 1] + tre[rt << 1 | 1]) % p; } void push_down(int rt, int l, int r) { if(lzyadd[rt] == 0 && lzymup[rt] == 1) return; int mid = l + r >> 1; tre[rt << 1] = (tre[rt << 1] * lzymup[rt] + (mid - l + 1) * lzyadd[rt]) % p; tre[rt << 1 | 1] = (tre[rt << 1 | 1] * lzymup[rt] + (r - mid) * lzyadd[rt]) % p; lzymup[rt << 1] = lzymup[rt << 1] * lzymup[rt] % p; lzymup[rt << 1 | 1] = lzymup[rt << 1 | 1] * lzymup[rt] % p; lzyadd[rt << 1] = (lzyadd[rt << 1] * lzymup[rt] + lzyadd[rt]) % p; lzyadd[rt << 1 | 1] = (lzyadd[rt << 1 | 1] * lzymup[rt] + lzyadd[rt]) % p; lzyadd[rt] = 0; lzymup[rt] = 1; return; } void build(int rt, int l, int r) { lzyadd[rt] = 0; lzymup[rt] = 1; if(l == r) { cin >> tre[rt]; tre[rt] = tre[rt] % p; return; } int mid = l + r >> 1; build(rt << 1, l, mid); build(rt << 1 | 1, mid + 1, r); push_up(rt); } void update(int rt, int l, int r, int L, int R, bool op, int x) { if(L <= l && r <= R) { if(op) { tre[rt] = tre[rt] * x % p; lzymup[rt] = lzymup[rt] * x % p; lzyadd[rt] = lzyadd[rt] * x % p; } else { lzyadd[rt] = (lzyadd[rt] + x) % p; tre[rt] = (tre[rt] + (r - l + 1) * x) % p; } return; } push_down(rt, l, r); int mid = l + r >> 1; if(L <= mid) update(rt << 1, l, mid, L, R, op, x); if(mid < R) update(rt << 1 | 1, mid + 1, r, L, R, op, x); push_up(rt); } ll query(int rt, int l, int r, int L, int R) { if(L <= l && r <= R) return tre[rt]; push_down(rt, l, r); int mid = l + r >> 1; ll res = 0; if(L <= mid) res = (res % p + query(rt << 1, l, mid, L, R) % p) % p; if(R > mid) res = (res % p + query(rt << 1 | 1, mid + 1, r, L, R) % p) % p; push_up(rt); return res; } int main() { ios::sync_with_stdio(false); cin.tie(0); cin >> n >> m >> p; build(1, 1, n); int op, x, y, z; while(m--) { cin >> op; if(op == 1) { cin >> x >> y >> z; update(1, 1, n, x, y, 1, z); } else if(op == 2) { cin >> x >> y >> z; update(1, 1, n, x, y, 0, z); } else if(op == 3) { cin >> x >> y; cout << query(1, 1, n, x, y) << endl; } } }