No problem; with a modern enough compiler (with decent C++17 support), the following should work:
#include <bits/stdc++.h>
using namespace std;
using ll = long long int;
class SegmentTree {
private:
ll default_value;
vector<ll> tree;
vector<ll> carry;
int length;
inline static function<ll(ll, ll)> sum = [](const ll a, const ll b) {return a + b;};
function<long(long, long)> key;
public:
SegmentTree(vector<int> a, int def_value = 0, function<ll(ll, ll)> function = sum) {
default_value = def_value;
key = function;
vector<int> arr(a.begin(), a.end());
int n = arr.size();
while ((n & (n - 1)) != 0) {
n++;
arr.push_back(default_value);
}
tree.resize(2 * n, default_value);
for(int i = 0; i < n; i++) {
tree[n + i] = arr[i];
}
for(int i = n - 1; i > 0; i--) {
tree[i] = key(tree[2 * i], tree[2 * i + 1]);
}
length = ((int)(tree.size())) / 2;
carry.resize(2 * n, default_value);
}
int size() {
return length;
}
void pointUpdate(int index, long value) {
pointUpdate(1, 0, length - 1, index, value);
}
private:
long pointUpdate(int node, int node_lb, int node_ub, int index, long value) {
if(index < node_lb || node_ub < index) {
return tree[node];
}
else if(node_lb == node_ub && node_ub == index) {
tree[node] = value;
}
else {
long leftReturned = pointUpdate(2 * node, node_lb, (node_lb + node_ub) / 2, index, value);
long rightReturned = pointUpdate(2 * node + 1, (node_lb + node_ub) / 2 + 1, node_ub, index, value);
tree[node] = key(leftReturned, rightReturned);
}
return tree[node];
}
public:
void rangeUpdate(int range_lb, int range_ub, long value) {
rangeUpdate(1, 0, length - 1, range_lb, range_ub, value);
}
private:
long rangeUpdate(int node, int node_lb, int node_ub, int range_lb, int range_ub, long value) {
if(range_lb <= node_lb && node_ub <= range_ub) {
carry[node] = key(carry[node], value);
}
else if(node_ub < range_lb || range_ub < node_lb) {
return carry[node];
}
else {
rangeUpdate(2 * node, node_lb, (node_lb + node_ub) / 2, range_lb, range_ub, value);
rangeUpdate(2 * node + 1, (node_lb + node_ub) / 2 + 1, node_ub, range_lb, range_ub, value);
}
return carry[node];
}
public:
long rangeQuery(int query_lb, int query_ub) {
return rangeQuery(1, 0, length - 1, query_lb, query_ub);
}
private:
long rangeQuery(int node, int node_lb, int node_ub, int query_lb, int query_ub) {
if(query_lb <= node_lb && node_ub <= query_ub) {
return key(tree[node], carry[node]);
}
else if(query_ub < node_lb || node_ub < query_lb) {
return default_value;
}
else {
long leftReturned = rangeQuery(2 * node, node_lb, (node_lb + node_ub) / 2, query_lb, query_ub);
long rightReturned = rangeQuery(2 * node + 1, (node_lb + node_ub) / 2 + 1, node_ub, query_lb, query_ub);
return key(leftReturned, rightReturned);
}
}
};
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int n, q;
cin >> n >> q;
vector<int> a(n);
for(int i = 0; i < n; i++) {
cin >> a[i];
}
SegmentTree tree = SegmentTree(a);
for(int i = 0; i < q; i++) {
int type;
cin >> type;
if(type == 1) {
int index, value;
cin >> index >> value;
tree.pointUpdate(index - 1, value);
}
else {
int lb, ub;
cin >> lb >> ub;
cout << tree.rangeQuery(lb - 1, ub - 1) << '\n';
}
}
return 0;
}