#include <bits/stdc++.h>
using namespace std;
ifstream fin("datorii.in");
ofstream fout("datorii.out");
const int UPDATE_QUERY_TYPE = 0;
const int SUM_QUERY_TYPE = 1;
class SegmentTree {
private:
static constexpr int ROOT_NODE_INDEX = 1;
vector<int> nodeValue;
int arrayLength;
public:
SegmentTree(const vector<short>& numbers) {
arrayLength = numbers.size();
nodeValue = vector<int>(getSegmentTreeSize(arrayLength));
for (int i = 0; i < arrayLength; i++) {
add(i, numbers[i]);
}
}
void add(int position, int value) {
add(position, value, ROOT_NODE_INDEX, 0, arrayLength - 1);
}
int getSum(int leftIndex, int rightIndex) const {
return getSum(leftIndex, rightIndex, ROOT_NODE_INDEX, 0, arrayLength - 1);
}
private:
void add(int position, int value, int node, int nodeSegmentLeftIndex, int nodeSegmentRightIndex) {
// we are in the node whose index is "node", and nodeValue[node]=array[nodeLeft]+...+array[nodeRight]
if (nodeSegmentLeftIndex == nodeSegmentRightIndex) {
nodeValue[node] += value;
return;
}
int middleIndex = (nodeSegmentLeftIndex + nodeSegmentRightIndex) / 2;
int leftChildNode = 2 * node;
int rightChildNode = leftChildNode + 1;
// left child: 2*node, nodeValue[2*node]=sum from nodeSegmentLeftIndex, middleIndex
// right child:2*node+1, ...
if (position <= middleIndex) {
add(position, value, leftChildNode, nodeSegmentLeftIndex, middleIndex);
} else {
add(position, value, rightChildNode, middleIndex + 1, nodeSegmentRightIndex);
}
nodeValue[node] += value;
}
int getSum(int leftIndex, int rightIndex, int node, int nodeSegmentLeftIndex, int nodeSegmentRightIndex) const {
if (isRangeWithinRange(nodeSegmentLeftIndex, nodeSegmentRightIndex, leftIndex, rightIndex)) {
return nodeValue[node];
}
int middleIndex = (nodeSegmentLeftIndex + nodeSegmentRightIndex) / 2;
int leftChildNode = 2 * node;
int rightChildNode = leftChildNode + 1;
int subtreeSum = 0;
if (leftIndex <= middleIndex) {
subtreeSum += getSum(leftIndex, rightIndex, leftChildNode, nodeSegmentLeftIndex, middleIndex);
}
if (rightIndex > middleIndex) {
subtreeSum += getSum(leftIndex, rightIndex, rightChildNode, middleIndex + 1, nodeSegmentRightIndex);
}
return subtreeSum;
}
private:
static int constexpr getSegmentTreeSize(int arrayLength) {
return 4 * arrayLength;
}
static int constexpr isRangeWithinRange(int firstRangeLeft, int firstRangeRight, int secondRangeLeft, int secondRangeRight) {
return firstRangeLeft >= secondRangeLeft && firstRangeRight <= secondRangeRight;
}
};
vector<short> readNumbers(int arrayLength) {
vector<short> numbers(arrayLength);
for (int i = 0; i < arrayLength; i++) {
fin >> numbers[i];
}
return numbers;
}
void processUpdate(SegmentTree& segmentTree) {
int position;
int value;
fin >> position >> value;
segmentTree.add(position - 1, -value);
}
int processGetSum(SegmentTree& segmentTree) {
int leftIndex;
int rightIndex;
fin >> leftIndex >> rightIndex;
return segmentTree.getSum(leftIndex - 1, rightIndex - 1);
}
void processQueries(int countQueries, SegmentTree& segmentTree) {
for (int i = 0; i < countQueries; i++) {
int queryType;
fin >> queryType;
if (queryType == UPDATE_QUERY_TYPE) {
processUpdate(segmentTree);
} else {
fout << processGetSum(segmentTree) << "\n";
}
}
}
int main() {
int arrayLength;
int countQueries;
fin >> arrayLength >> countQueries;
vector<short> numbers = readNumbers(arrayLength); // do we need move here? or is it automatically moved?
SegmentTree segmentTree{ numbers };
processQueries(countQueries, segmentTree);
return 0;
}