1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
|
#include <bits/stdc++.h> using namespace std;
template<typename T> class SegmentTreeNode { vector<T>* vec; T _sum = 0; T pending_change = 0; int left_bound, right_bound, length, mid; SegmentTreeNode *left_child = NULL, *right_child = NULL; bool initialized = false; void initializer(vector<T>& v, int lb, int rb){ if(lb > rb || lb < 0 || rb > (int)(v.size())-1) throw invalid_argument("Invalid bounds."); vec = &v; left_bound = lb; right_bound = rb; length = rb - lb; mid = lb + length / 2; } public: SegmentTreeNode(vector<T>& v, int lb, int rb) { initializer(v, lb, rb); } SegmentTreeNode(vector<T>& v) { initializer(v, 0, (int)(v.size())-1); } ~SegmentTreeNode() { if (left_child != NULL) delete left_child; if (right_child != NULL) delete right_child; } void range_add(const int lb, const int rb, const T n) { if (lb > rb || lb < left_bound || rb > right_bound) throw invalid_argument("invalid bounds!"); if (lb == left_bound && rb == right_bound) return add_pending(n); _sum += n * (rb - lb + 1); const bool at_left = lb <= mid, at_right = rb > mid; if (at_left) left()->range_add(lb, min(rb, mid), n); if (at_right) right()->range_add(max(lb, mid + 1), rb, n); } uint64_t range_sum(const int lb, const int rb) { if (lb > rb || lb < left_bound || rb > right_bound) throw invalid_argument("invalid bounds!"); if (lb == left_bound && rb == right_bound) return sum(); const bool at_left = lb <= mid, at_right = rb > mid; if (pending_change) { left()->add_pending(pending_change); right()->add_pending(pending_change); _sum += pending_change * (length + 1); pending_change = 0; } T rs = 0; if (at_left) rs += left()->range_sum(lb, min(rb, mid)); if (at_right) rs += right()->range_sum(max(lb, mid + 1), rb); return rs; } uint64_t sum() { if (!initialized) { if (length) _sum = left()->sum() + right()->sum(); else _sum = (*vec)[left_bound]; initialized = true; } return _sum + pending_change * (length + 1); } SegmentTreeNode* left() { if (!length) throw invalid_argument("cannot create subtree because the node is leaf."); if (left_child == NULL) left_child = new SegmentTreeNode(*vec, left_bound, mid); return left_child; } SegmentTreeNode* right() { if (!length) throw invalid_argument("cannot create subtree because the node is leaf."); if (right_child == NULL) right_child = new SegmentTreeNode(*vec, mid + 1, right_bound); return right_child; } void add_pending(const uint64_t n) { pending_change += n; } };
int main() {
vector<uint64_t> a; uint64_t n, m; cin >> n >> m; a.reserve(n); while(n--){ uint64_t x; cin >> x; a.emplace_back(x); } SegmentTreeNode<uint64_t> tree(a); while(m--){ uint64_t t, x, y, k; cin >> t; switch(t){ case 1: cin >> x >> y >> k; tree.range_add(x-1, y-1, k); break; case 2: cin >> x >> y; cout << tree.range_sum(x-1, y-1) << endl; break; } } return 0; }
|