一个区间修改线段树的模板题,不过挺有意思的,每个格子有一个单位价格,要把一段区间的总价格算出来,每次update一个区间的重量。
发现总价格实际上是满足结合律的。直接上线段树。
#include<bits/stdc++.h> using namespace std; typedef long long ll; #define lt ls, l, m #define rt rs, m + 1, r #define ls (o<<1) #define rs (o<<1|1) const ll mod = 1008610010; const int MAXM = 100000 + 5; ll a[MAXM]; ll st[MAXM * 4], p[MAXM * 4], lazy[MAXM * 4]; inline void PushUp(int o) { st[o] = (st[ls] + st[rs]) % mod; } inline void PushDown(int o, int l, int r) { if(lazy[o]) { lazy[ls] = (lazy[ls] + lazy[o]) % mod; lazy[rs] = (lazy[rs] + lazy[o]) % mod; int m = l + r >> 1; st[ls] = (st[ls] + lazy[o] * p[ls] % mod) % mod; st[rs] = (st[rs] + lazy[o] * p[rs] % mod) % mod; lazy[o] = 0; } } void Build(int o, int l, int r) { if(l == r) { p[o] = a[l]; st[o] = 0; } else { int m = l + r >> 1; Build(lt); Build(rt); p[o] = (p[ls] + p[rs]) % mod; } lazy[o] = 0; } void Update(int o, int l, int r, int ql, int qr, ll v) { if(ql <= l && r <= qr) { lazy[o] = (lazy[o] + v) % mod; st[o] = (st[o] + v * p[o] % mod) % mod; return; } else { PushDown(o, l, r); int m = l + r >> 1; if(ql <= m) Update(lt, ql, qr, v); if(qr >= m + 1) Update(rt, ql, qr, v); PushUp(o); } } ll Query(int o, int l, int r, int ql, int qr) { if(ql <= l && r <= qr) { return st[o]; } else { PushDown(o, l, r); int m = l + r >> 1; ll res = 0; if(ql <= m) res = res + Query(lt, ql, qr); if(qr >= m + 1) res = res + Query(rt, ql, qr); return res % mod; } } int main() { #ifdef Yinku freopen("Yinku.in", "r", stdin); #endif // Yinku int n, m; scanf("%d", &n); for(int i = 1; i <= n; ++i) { scanf("%d", &a[i]); } Build(1, 1, n); scanf("%d", &m); int op, x, y, k; while(m--) { scanf("%d%d%d", &op, &x, &y); if(op == 1) { scanf("%d", &k); Update(1, 1, n, x, y, k); } else { printf("%lld\n", Query(1, 1, n, x, y) % mod); } } return 0; }