Cod sursa(job #3251284)

Utilizator Ioana38Bejenaru Ioana Ioana38 Data 25 octombrie 2024 16:32:29
Problema Datorii Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.92 kb


#include <fstream>
#include <vector>

using namespace std;

ifstream fin("datorii.in");
ofstream fout("datorii.out");


//trebuie sa fie neaparat global
//se trimit copii prin CC si nu se modifica
vector <int> segment_tree;
vector <int> valori;
//toata ideea e sa construim subarbori cu sumele de pe un anumit interval
//facem asta pornind cu toate nodurile si vrem sa construim suma pt prima jumatate si pt a doua
//mergem recursiv asa pana ajungem sa avem un singur nod caruia ii stim suma, adica valoarea lui
//in nodul 1 o sa avem suma totala a vectorului
void Construieste(int nod, int left, int right)
{
    if(left == right)
        segment_tree[nod] = valori[left];
    else
    {
        int mij = (left + right) / 2;
        //std::cout << nod << " " << left << " " << mij << " " << right << "\n";
        Construieste(nod * 2, left, mij);
        Construieste(nod * 2 + 1, mij + 1, right);
        //std::cout << nod << " " << segment_tree[nod * 2] << " " << segment_tree[nod * 2 + 1] << "\n";
        segment_tree[nod] = segment_tree[nod * 2] + segment_tree[nod * 2 + 1];

    }

}

void Modifica(int nod, int left, int right, int x, int y)
{
    if(left == right)
    {
        valori[left] -= y;
        segment_tree[nod] -= y;
    }
    else
    {
        int mij = (left + right) / 2;
        if(x <= mij)
            Modifica(nod * 2, left, mij, x, y);
        else Modifica(nod * 2 + 1, mij + 1, right, x, y);
        segment_tree[nod] = segment_tree[nod * 2] + segment_tree[nod * 2 + 1];
    }
}

int Afiseaza(int nod, int left, int right, int x, int y)
{
    //daca nu e in interval
    //ne am dus pe un subarbore de care nu avem nevoie
    if(y < left || right < x)
        return 0;
    //daca toata suma intervalului tinut de nodul nod este cuprinsa
    //in intervalul pe care vrem sa il calculam
    if(x <= left && right <= y)
        return segment_tree[nod];
    //daca nu
    //micsoram intervalul incat sa fie cuprins
    int mij = (left + right) / 2;
    return Afiseaza(nod * 2, left, mij, x, y) + Afiseaza(nod * 2 + 1, mij + 1, right, x, y);
}

void A() {
    for(int i = 0; i < segment_tree.size(); i++)
        fout << segment_tree[i] << " ";
    fout << '\n';
}

int main()
{
    int N, M;
    fin >> N >> M;
    int val, x, y;
    for(int i = 0; i < N; i++)
    {
        fin>> val;
        valori.push_back(val);
    }
    segment_tree.resize(4 * N, 0);
    //construim arborele binar unde in radacina avem suma tuturor elementelor
    //in subarborele stang suma primelor ~ N / 2 elem, respectiv in subarborele drept cealalta jumatate
    //left = 0 si right = N - 1, deoarece avem procedeul de Divide Et Imepera si vrem sa obtinem
    //jumatate din elemente in fiecare subarbore de noduri n
    Construieste(1, 0, N - 1);
    //A();
    for(int i = 0; i < M; i++)
    {
       fin >> val >> x >> y;
       if(val == 0)
           Modifica(1, 0, N - 1, x - 1, y); //A();
       else fout << Afiseaza(1, 0, N - 1, x - 1, y - 1) << '\n';
    }
}