Cod sursa(job #2763233)

Utilizator borcanirobertBorcani Robert borcanirobert Data 12 iulie 2021 16:57:48
Problema Arbori de intervale Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.85 kb
#include <iostream>
#include <fstream>

class SegmentTree{
public:
    /// Creeaza un nou arbore de intervale pentru intervalul [x, y]
    /// Parametrii:
    ///      x: Inceputul intervalului
    ///      y: Finalul intervalului
    /// Complexitate: Theta(n*log(n))
    /// Complexitate spatiu: Theta(n*log(n)), unde n = y - x + 1
    SegmentTree(int x, int y):
        x{x}, y{y}, val{INITIAL_VALUE}, valToPropagate{INITIAL_VALUE}, needToPropagate{false}, left{nullptr}, right{nullptr}
    {
        if (x != y)
        {
            int mid = (x + y) / 2;
            left = new SegmentTree(x, mid);
            right = new SegmentTree(mid + 1, y);
        }
    }

    /// Actualizeaza valoarea de pe pozitiile din intervalul [p1, p2] cu valoarea data (value)
    /// Parametrii:
    ///     p1: Inceputul intervalului de actualizare
    ///     p2: Finalul intervalului de actualizare
    ///     value: Valoarea cu care se actualizeaza
    /// Complexitate: O(log(n))
    void Update(int p1, int p2, int value)
    {
        Propagate();

        if (p2 < x || p1 > y)   // asta inseamna ca sunt intr-un interval care nu contine pozitia pe care o caut
            return;
        
        if (p1 <= x && y <= p2)    // Am ajuns la un interval care e inclus in intervalul in care am de cautat
        {
            valToPropagate = value;
            needToPropagate = true;
            Propagate();
            return;
        }

        // Trimit Update-ul spre stanga si spre dreapta
        left->Update(p1, p2, value);
        right->Update(p1, p2, value);

        // Actualizez valoarea din nodul curent, care retine informatii pentru tot intervalul [x, y]
        val = std::max(left->val,right->val);   // pentru sume
    }

    /// Se gaseste suma/maximul/minimul pe intervalul [lo, hi]
    /// Parametrii:
    ///     lo: Inceputul intervalului pentru query
    ///     hi: Finalul intervalului pentru query
    /// Complexitate: O(log(n))
    int Query(int lo, int hi)   // Care este suma/minimul/maximul din intervalul [lo, hi]
    {
        Propagate();

        if (y < lo || x > hi)   // sunt in afara intervalului pentru query
            return INITIAL_VALUE;
        
        if (lo <= x && y <= hi) // intervalul curent este inclus de intervalul pe care il caut
            return val;
        
        int t1 = left->Query(lo, hi);
        int t2 = right->Query(lo, hi);

        return std::max(t1, t2);
    }
private:
    void Propagate()
    {
        if (!needToPropagate)           // daca totul e actualizat
            return;

        if (left != nullptr)
        {
            left->valToPropagate = valToPropagate;
            right->valToPropagate = valToPropagate;
        }

        val = valToPropagate;

        valToPropagate = INITIAL_VALUE;
        needToPropagate = false;
    }

    int x, y;   // intervalul pe care il retine nodul curent
    int val;    // valoarea de la acest nod - poate fi o suma, un minim, un maxim etc.
    int valToPropagate; // aceasta valoare trebuie actualizata pe tot intervalul [x, y], pe masura ce inaintam in arbore de la acest nod in jos
    bool needToPropagate;       // true daca trebuie actualizat intervalul [x, y] cu ceea ce se afla in valToPropagate
    SegmentTree *left, *right;      // fiul stang si fiul drept al arborelui

    const static int INITIAL_VALUE = 0;     // Ar trebui sa fie valoarea initiala din sir. Pentru sume e 0
};

int main()
{
    std::ifstream fin("arbint.in");
    std::ofstream fout("arbint.out");

    int N, Q;
    int type, a, b;

    fin >> N >> Q;
    SegmentTree st(1, N);
    for (int i = 1; i <= N; ++i)
    {
        fin >> a;

        st.Update(i, i, a);
    }

    while (Q--)
    {
        fin >> type >> a >> b;

        if (type == 0)
        {
            fout << st.Query(a, b) << '\n';
        }
        else
        {
            st.Update(a, a, b);
        }
    }

    fin.close();
    fout.close();
}