Cod sursa(job #3370078)

Utilizator DavidLDavid Lauran DavidL Data 23 octombrie 2026 22:54:24
Problema Datorii Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.98 kb
#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;
}