Cod sursa(job #3234140)

Utilizator code_blocksSpiridon Mihnea-Andrei code_blocks Data 6 iunie 2024 18:00:15
Problema Arbori de intervale Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.62 kb
#include <iostream>
#include <fstream>
#include <vector>

using namespace std;

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

// Segment tree = arbore de intervale
struct St
{
    int l, r, x;
    St *ltree, *rtree;

    St(int l, int r, int x, St *ltree, St *rtree) 
    : l(l), r(r), x(x), ltree(ltree), rtree(rtree) {}
};

// Construiește arborele de intervale pe [l, r]
// folosindu-se de valorile din v
St* build(const vector<int>& v, int l, int r)
{
    St *ltree = nullptr, *rtree = nullptr;
    int x, m = (l + r) / 2;

    if(l == r) // Dacă e frunză, nu avem subarbori, valoarea e egală cu cea din vector
        x = v[m];
    else // Dacă nu e frunză
    {
        // Construim subarborii
        ltree = build(v, l, m);
        rtree = build(v, m + 1, r);

        // Și calculăm valoarea proprie
        x = max(ltree->x, rtree->x);
    }

    return new St(l, r, x, ltree, rtree);
}

int query(St *root, int l, int r)
{
    // Dacă intervalul se suprapune exact
    if(root->l == l && root->r == r)
        return root->x;
    
    // Dacă intervalul e inclus complet în subarborele stâng
    else if(r <= root->ltree->r)
        return query(root->ltree, l, r);

    // Dacă intervalul e inclus complet în subarborele drept
    else if(l >= root->rtree->l)
        return query(root->rtree, l, r);

    // Dacă intervalul pătrunde în ambii subarbori
    else
    {
        int lx = query(root->ltree, l, root->ltree->r);
        int rx = query(root->rtree, root->rtree->l, r);
        return max(lx, rx);
    }
}

void update(St *root, int p, int k)
{
    // Frunza primește pur și simplu valoarea nouă
    if(!root->ltree && !root->rtree)
        root->x = k;
    
    // Actualizăm subarborele stâng
    if(root->ltree)
        if(p <= root->ltree->r)
            update(root->ltree, p, k);
    
    // Actualizăm subarborele drept
    if(root->rtree)
        if(p >= root->rtree->l)
            update(root->rtree, p, k);

    // Subarborii își recalculează valorile
    if(root->ltree && root->rtree)
        root->x = max(root->ltree->x, root->rtree->x);
}

int main()
{
    int n, q;
    fin >> n >> q;
    
    vector<int> v(n + 1);
    for(int i = 1; i <= n; i++)
        fin >> v[i];

    St *root = build(v, 1, n);

    for(int i = 1; i <= q; i++)
    {
        int t, a, b;
        fin >> t >> a >> b;

        if(t == 0) // Interogare
            fout << query(root, a, b) << '\n';
        else if(t == 1) // Actualizare
            update(root, a, b);
    }

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

    return 0;
}