Cod sursa(job #2756263)

Utilizator NeacsuMihaiNeacsu Mihai NeacsuMihai Data 30 mai 2021 14:43:03
Problema Arbori de intervale Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.68 kb
#include <iostream>
#include <fstream>

//#define INFINIT 1000000001 //10^9 + 1
#define NMAX 100000 //10^5

using namespace std;

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

int tree[4 * NMAX + 1];
int v[NMAX + 1];

void buildArbore(int node, int left, int right){
    if(left == right){
        //frunza
        tree[node] = v[left];
        return;
    }

    int mid = left + (right - left) / 2;
    //aici nu mai fac nicio decizie, pur si simplu actualizez fiii si aia e
    buildArbore(node * 2, left, mid);
    buildArbore(node * 2 + 1, mid + 1, right);

    tree[node] = max(tree[node * 2], tree[node * 2 + 1]);
}

int st, dr;
int query(int node, int left, int right){
    if(st <= left && right <= dr){
        //intervalul in care ma aflu este cuprins in intregime in intervalul de query
        return tree[node];
    }

    ///aici ajung doar daca [left, right] nu e complet inclus in [st, dr]
    ///dar daca am ajuns aici inseamna ca poate sa imi mai ofere ceva intervalul [left, right]
    ///asa ca decid in care fii sa ma duc
    int mid = left + (right - left) / 2;

    int rez1 = -1, rez2 = -1; ///virgula intre ele pt ca nu conteaza ordinea
    if(st <= mid){
        //inseamna ca fiul din stanga mai poate sa ma ajute cu ceva, deci ma duc si in el
        rez1 = query(node * 2, left, mid);
    }
    if(dr >= mid + 1){
        //inseamna ca fiul din dreapta mai poate sa ma ajute cu ceva, deci ma duc si in el
        rez2 = query(node * 2 + 1, mid + 1, right);
    }

    return max(rez1, rez2); //adica maximul query-urilor din fii
    //iar daca nu ma duc in query intr-un anumit fiu, atunci e -1
    //adica il prefera pe celalalt orice ar fi
    //si daca am ajuns pana aici, sigur unul din rez1 sau rez2 o sa fie diferit de -1!
    //pt ca, la fel cum am zis mai sus, daca am ajuns in [left, right] inseamna ca mai are ceva sa imi ofere
    //si daca [left, right] nu e inclus complet in interval, atunci sigur minim unul din fiii lui [left, right] are ceva sa imi ofere (chiar ambii se poate)
}

int pozAct, valAct;
void update(int node, int left, int right){
    //vreau sa actualizez maximul din [left, right]
    /// !!!!!!! daca am ajuns pana aici, stiu sigur ca elementul pe care vreau sa il actualizez se afla ca pozitie in intervalul [left, right]
    if(left == right){
        //inseamna ca left = pozAct
        tree[node] = valAct;
        return;
    }

    int mid = left + (right - left) / 2;

    ///vreau sa actualizez fiul care contine pozAct
    ///stiu deja, conform ce am scris mai sus, ca pozAct e cuprins intre [left, right]
    ///si acum vreua sa vad daca e in [left, mid] sau in [mid + 1, right]
    if(pozAct <= mid){
        ///e in fiul din stanga atunci
        update(node * 2, left, mid);
    }
    else {
        update(node * 2 + 1, mid + 1, right);
    }

    ///acum ca am actualizat unul din fii, actualizez si intervalul [left, right]
    tree[node] = max(tree[node * 2], tree[node * 2 + 1]);
}

int main()
{
    int N, M;
    fin >> N >> M;

    for(int i = 1; i <= N; i++){
        fin >> v[i];
    }
    buildArbore(1, 1, N);

    for(int q = 1; q <= M; q++){
        //cout << "q = " << q << "\n";
        int tip, a, b;
        fin >> tip >> a >> b;

        if(tip == 0){
            //query
            ///variabile globale, ca sa nu ma car cu ele ca parametrii ale functiei
            st = a;
            dr = b;
            fout << query(1, 1, N) << "\n";
        }
        else {
            //update
            ///variabile globale, ca mai sus
            pozAct = a;
            valAct = b;

            update(1, 1, N);
        }
    }

    return 0;
}