void pushdown(int l, int r, int rt) { if (lazy[rt]) { sum[rt << 1] += l * lazy[rt]; sum[(rt << 1) + 1] += r * lazy[rt]; lazy[rt << 1] += lazy[rt]; lazy[(rt << 1) + 1] += lazy[rt]; lazy[rt] = 0; } } void build(int l, int r, int rt) { if (l == r) { sum[rt] = tmp[l]; return; } int mid = (l + r) >> 1; build(l, mid, rt << 1); build(mid + 1, r, (rt << 1) + 1); sum[rt] = sum[rt << 1] + sum[(rt << 1) + 1]; } void update(int l, int r, int rt, int l1, int r1, int v) { if (l1 <= l && r <= r1) { sum[rt] += v * (r - l + 1); lazy[rt] += v; return; } int mid = (l + r) >> 1; pushdown(mid - l + 1, r - mid, rt); if (l1 <= mid) update(l, mid, rt << 1, l1, r1, v); if (r1 > mid) update(mid + 1, r, (rt << 1) + 1, l1, r1, v); sum[rt] = sum[rt << 1] + sum[(rt << 1) + 1]; } int query(int l, int r, int rt, int l1, int r1) { if (l1 <= l && r <= r1) return (ll)sum[rt]; int mid = (l + r) >> 1; int ret = 0; pushdown(mid - l + 1, r - mid, rt); if (l1 <= mid) ret += query(l, mid, rt << 1, l1, r1); if (r1 > mid) ret += query(mid + 1, r, (rt << 1) + 1, l1, r1); sum[rt] = sum[rt << 1] + sum[(rt << 1) + 1]; return ret; }
线段树区间加法,区间乘法,区间查询
#include <bits/stdc++.h> #define ll long long #define ull unsigned long long #define met(a,x) memset(a,x,sizeof(a)) #define inf 0x3f3f3f3f #define mp make_pair; using namespace std; const int maxn = 100000 + 10; const int mod=1e9+7; ll A[maxn << 1], Sum[maxn << 3], Add[maxn << 3], Mul[maxn << 3]; ll n, s, p; void PushUp(ll rt) { Sum[rt] = (Sum[rt << 1] + Sum[rt << 1 | 1]) % p; }//上推函数 void PushDown(ll rt, ll m)//下推函数,注意乘法优先级比加法高 { if (Add[rt] || Mul[rt] != 1) { Sum[rt << 1] = (Sum[rt << 1] * Mul[rt] + Add[rt] * (m - (m >> 1))) % p; Sum[rt << 1 | 1] = (Sum[rt << 1 | 1] * Mul[rt] + Add[rt] * (m >> 1)) % p; Add[rt << 1] = (Add[rt << 1] * Mul[rt] + Add[rt]) % p; Add[rt << 1 | 1] = (Add[rt << 1 | 1] * Mul[rt] + Add[rt]) % p; Mul[rt << 1] = (Mul[rt << 1] * Mul[rt]) % p; Mul[rt << 1 | 1] = (Mul[rt << 1 | 1] * Mul[rt]) % p; Add[rt] = 0; Mul[rt] = 1; } } void Build(ll l, ll r, ll rt)//建树 { Add[rt] = 0; Mul[rt] = 1; if (l == r) { Sum[rt] = A[l] % p; return; } ll m = (l + r) >> 1; Build(l, m, rt << 1); Build(m + 1, r, rt << 1 | 1); PushUp(rt); } void Update_mul(ll L, ll R, ll C, ll l, ll r, ll rt)//区间乘法运算 { PushDown(rt, (r - l + 1)); if (L <= l && r <= R) { Sum[rt] = Sum[rt] * C; Sum[rt] = Sum[rt] % p; Mul[rt] = Mul[rt] * C; Mul[rt] = Mul[rt] % p; return; } ll m = (l + r) >> 1; if (L <= m) Update_mul(L, R, C, l, m, rt << 1); if (R > m) Update_mul(L, R, C, m + 1, r, rt << 1 | 1); PushUp(rt); } void Update_plu(ll L, ll R, ll C, ll l, ll r, ll rt)//区间加法运算 { PushDown(rt, r - l + 1); if (L <= l && r <= R) { Sum[rt] = (Sum[rt] + (r - l + 1) * C) % p; Add[rt] = (Add[rt] + C) % p; return; } ll m = (l + r) >> 1; if (L <= m) Update_plu(L, R, C, l, m, rt << 1); if (R > m) Update_plu(L, R, C, m + 1, r, rt << 1 | 1); PushUp(rt); } ll Query(ll L, ll R, ll l, ll r, ll rt)//区间查询 { PushDown(rt, r - l + 1); if (L <= l && r <= R) { return Sum[rt]; } ll m = (l + r) >> 1, Ans = 0; if (L <= m) Ans = (Ans + Query(L, R, l, m, rt << 1)) % p; if (R > m) Ans = (Ans + Query(L, R, m + 1, r, rt << 1 | 1)) % p; return Ans; } int main()//各种操作 { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); scanf("%lld%lld", &n, &p); for (int i = 1; i <= n; i++) scanf("%lld", &A[i]); Build(1, n, 1); scanf("%lld", &s); for (int i = 1; i <= s; i++) { ll t, x, y, k; scanf("%lld%lld%lld", &t, &x, &y); if (t == 1) { scanf("%lld", &k); Update_mul(x, y, k, 1, n, 1); } if (t == 2) { scanf("%lld", &k); Update_plu(x, y, k, 1, n, 1); } if (t == 3) { printf("%lld ", Query(x, y, 1, n, 1)); } } return 0; }