/** * Segment tree - O(n) build time * finds the sum of all elements * in a given interval in log(n) time * adds a value to all elements in an * interval in log(n) time (lazy propagation) */ #include #define endl '\n' #define fileIn(a) freopen(a, "r", stdin) #define fileOut(a) freopen(a, "w", stdout) using namespace std; const int SIZE = 1 << 18; int n; int arr[SIZE]; struct Node { int val, carry; int from, to; Node* left; Node* right; /// push function for the lazy updating void push() { val += (to - from + 1) * carry; if (left) { left->carry += carry; right->carry += carry; } carry = 0; } }; Node memoryHolder[2 * SIZE]; int memCnt; Node* root; void build(Node* node, int from, int to) { node->from = from; node->to = to; node->carry = 0; if (from == to) { node->val = arr[to]; return; } node->left = &memoryHolder[memCnt++]; node->right = &memoryHolder[memCnt++]; int mid = (from + to) / 2; build(node->left, from, mid); build(node->right, mid + 1, to); /// Other possible functions /// /// node->val = min(node->left->val, node->right->val); /// node->val = max(node->left->val, node->right->val); /// node->val = __gcd(node->left->val, node->right->val); /// node->val = lcm(node->left->val, node->right->val); /// node-> val = node->left->val ^ node->right->val; /// node-> val = node->left->val | node->right->val; /// node-> val = node->left->val & node->right->val; /// ... node->val = node->left->val + node->right->val; } int getSum(Node* node, int from, int to) { node->push(); if (from > node->to or to < node->from) return 0; if (from <= node->from and node->to <= to) return node->val; /// The return statement is based on the function /// /// return min(getSum(node->left, from, to), getSum(node->right, from, to)); /// return max(getSum(node->left, from, to), getSum(node->right, from, to)); /// return __gcd(getSum(node->left, from, to), getSum(node->right, from, to)); /// return getSum(node->left, from, to) ^ getSum(node->right, from, to); /// return getSum(node->left, from, to) | getSum(node->right, from, to); /// return getSum(node->left, from, to) & getSum(node->right, from, to); /// ... return getSum(node->left, from, to) + getSum(node->right, from, to); } void update(Node* node, int from, int to, int v) { if (from > node->to or to < node->from) return; if (from <= node->from and node->to <= to) { node->carry += v; node->push(); return; } node->push(); update(node->left, from, to, v); update(node->right, from, to, v); /// Update with the same function also /// /// node->val = min(node->left->val, node->right->val); /// node->val = max(node->left->val, node->right->val); /// node->val = __gcd(node->left->val, node->right->val); /// node->val = lcm(node->left->val, node->right->val); /// node-> val = node->left->val ^ node->right->val; /// node-> val = node->left->val | node->right->val; /// node-> val = node->left->val & node->right->val; /// ... node->val = node->left->val + node->right->val; } void input() { cin >> n; for (int i = 0; i < n; i++) cin >> arr[i]; root = new Node; build(root, 0, n - 1); } void solve() { /// Some queries to test the segment tree int q; cin >> q; for (int i = 0; i < q; i++) { int type; cin >> type; if (type == 1) { int from, to; cin >> from >> to; cout << getSum(root, from, to) << endl; } if (type == 2) { int from, to, v; cin >> from >> to >> v; update(root, from, to , v); } } } int main() { iostream::sync_with_stdio(false); cin.tie(nullptr); input(); solve(); return 0; }