線段樹(模板測試中)
阿新 • • 發佈:2018-12-29
#include<iostream> #include<cstdio> #include<cstring> const int N = 100000; typedef long long ll; ll sum[N << 2], lazy[N << 2]; void pushUp(const int &rt) { sum[rt] = sum[rt << 1] + sum[rt << 1 | 1]; } void pushDown(const int &rt, const int &L, const int &R) { if (lazy[rt]) { int mid = (L + R) >> 1; lazy[rt << 1] += lazy[rt]; sum[rt << 1] += (mid - L + 1)*lazy[rt]; lazy[rt << 1 | 1] += lazy[rt]; sum[rt << 1 | 1] += (R - mid)*lazy[rt]; lazy[rt] = 0; } } //建樹 void build(int rt, int L, int R) { lazy[rt] = 0; if (L == R) { scanf("%lld", &sum[rt]); return; } int mid = (L + R) >> 1; build(rt << 1, L, mid); build(rt << 1 | 1, mid + 1, R); pushUp(rt); } //單點更新 void update(int rt, int L, int R, const int &id, const int &val) { if (L == R) { sum[rt] += val; return; } int mid = (L + R) >> 1; if (id <= mid)update(rt << 1, L, mid, id, val); else update(rt << 1 | 1, mid + 1, R, id, val); pushUp(rt); } //區間更新 void update(int rt, int L, int R, const int &QL, const int &QR, const int &val) { if (QL <= L && R <= QR) { sum[rt] += (R - L + 1)*val; lazy[rt] += val; return; } pushDown(rt, L, R); int mid = (L + R) >> 1; if (QL <= mid)update(rt << 1, L, mid, QL, QR, val); if (mid < QR)update(rt << 1 | 1, mid + 1, R, QL, QR, val); pushUp(rt); } //單點查詢 ll query(int rt, int L, int R, const int &id, const int &val) { if (L == R)return sum[rt]; int mid = (L + R) >> 1; pushDown(rt, L, R); if (id <= mid)return query(rt << 1, L, mid, id, val); return query(rt << 1 | 1, mid + 1, R, id, val); } //區間查詢 ll query(int rt, int L, int R, const int &QL, const int &QR) { if (QL <= L && R <= QR)return sum[rt]; int mid = (L + R) >> 1; ll ans = 0; pushDown(rt, L, R); if (QL <= mid)ans += query(rt << 1, L, mid, QL, QR); if (mid < QR)ans += query(rt << 1 | 1, mid + 1, R, QL, QR); return ans; }