Cod sursa(job #2098277)

Utilizator dariusdariusMarian Darius dariusdarius Data 2 ianuarie 2018 17:06:11
Problema Datorii Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 4.59 kb
#include <algorithm>
#include <fstream>
#include <iostream>
#include <vector>
using namespace std;

int a[15005];

template<typename T, unsigned int startIndex=0ul>
class SegmentTree {

private:
    std::vector<T> segmTree;
    unsigned int size;
    
    T add(const T &left, const T &right) {
        return left + right;
    }
    
    template<typename GetNextItemType>
    void build(unsigned int node, unsigned int left, unsigned int right, const GetNextItemType &getNextItem) {
        if (left == right) {
            this->segmTree[node] = getNextItem();
        } else {
            unsigned int middle = left + ((right - left) >> 1);
            this->build((node << 1) + 1, left, middle, getNextItem);
            this->build((node << 1) + 2, middle + 1, right, getNextItem);
            this->segmTree[node] = this->add(this->segmTree[(node << 1) + 1], this->segmTree[(node << 1) + 2]);
        }
    }
    
    template<typename ChangeFuncType>
    void update(unsigned int node, unsigned int left, unsigned int right, unsigned int position, const ChangeFuncType &func) {
        if (left == right) {
            this->segmTree[node] = func(this->segmTree[node]);
        } else {
            unsigned int middle = left + ((right - left) >> 1);
            if (position <= middle) {
                this->update((node << 1) + 1, left, middle, position, func);
            } else {
                this->update((node << 1) + 2, middle + 1, right, position, func);
            }
            this->segmTree[node] = this->add(this->segmTree[(node << 1) + 1], this->segmTree[(node << 1) + 2]);
        }
    }
    
    T query(unsigned int node, unsigned int left, unsigned int right, unsigned int x, unsigned int y) {
        if (x <= left && right <= y) {
            return this->segmTree[node];
        } else {
            unsigned int middle = left + ((right - left) >> 1);
            if (x <= middle && y >= middle + 1) {
                T a = this->query((node << 1) + 1, left, middle, x, y);
                T b = this->query((node << 1) + 2, middle + 1, right, x, y);
                return this->add(a, b);
            }
            if (x <= middle) {
                return this->query((node << 1) + 1, left, middle, x, y);
            }
            return this->query((node << 1) + 2, middle + 1, right, x, y);
        }
    }

public:
    SegmentTree() = default;
    
    SegmentTree(unsigned int n) {
        this->size = n;
        this->segmTree.assign(this->size << 2);
    }
    
    SegmentTree(const void *begin, const void *end) {
        this->size = ((const unsigned char*)begin - (const unsigned char*)end) / sizeof(T);
        this->segmTree.assign(this->size << 2);
        void *it = begin;
        auto getNextItem = [&it]() {
            T aux = *((T*)it);
            it += sizeof(T);
            return aux;
        };
        this->build(0u, startIndex, startIndex + size - 1, getNextItem);
    }
    
    template<typename InputIterator>
    SegmentTree(const InputIterator &begin, const InputIterator &end) {
        this->size = 0;
        InputIterator it = begin;
        while (it != end) {
            ++ this->size;
            ++ it;
        }
        segmTree.assign(4 * this->size, T());
        it = begin;
        auto getNextItem = [&it]() {
            T aux = *it;
            ++ it;
            return aux;
        };
        this->build(0u, startIndex, startIndex + this->size - 1, getNextItem);
    }
    
    template<typename ChangeFuncType>
    void change(int position, const ChangeFuncType &func) {
        this->update(0u, startIndex, startIndex + this->size - 1, position, func);
    }
    
    void set(unsigned int position, const T &value) {
        this->update(0u, startIndex, startIndex + this->size - 1, position, [&value](const T &original) {
            return value;
        });
    }
    
    T query(unsigned int x, unsigned int y) {
        return this->query(0u, startIndex, startIndex + this->size - 1, x, y);
    }
};


int main() {
    ifstream cin("datorii.in");
    ofstream cout("datorii.out");
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; ++ i) {
        cin >> a[i];
    }
    SegmentTree<int, 1> tree(a + 1, a + n + 1);
    
    for (int i = 1; i <= m; ++ i) {
        int type, a, b;
        cin >> type >> a >> b;
        if (type == 0) {
            tree.change(a, [&b](const int &original) {
                return original - b;
            });
        } else {
            cout << tree.query(a, b) << "\n";
        }
    }
    
    return 0;
}