Cod sursa(job #2457535)

Utilizator igsifvevc avb igsi Data 17 septembrie 2019 23:00:33
Problema Arbori de intervale Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.29 kb
#include <algorithm>
#include <cmath>
#include <fstream>
#include <iterator>
#include <limits>
#include <vector>

class IntervalTree
{
public:
    IntervalTree(const std::vector<int> &v);
    void Add(int pos, int value);
    int Get(int a, int b) const;

private:
    std::vector<int> tree;
    int size;

    void add(int pos, int value, int i, int l, int r);
    int get(int a, int b, int i, int l, int r) const;
};

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

    int n, m, op, a, b;
    std::vector<int> v;

    fin >> n >> m;
    std::copy_n(std::istream_iterator<int>(fin), n, std::back_inserter(v));

    IntervalTree t(v);
    while (fin >> op >> a >> b)
    {
        switch (op)
        {
        case 0:
            a--, b--;
            fout << t.Get(a, b) << '\n';
            break;
        case 1:
            a--;
            t.Add(a, b);
            break;
        }
    }

    return 0;
}

IntervalTree::IntervalTree(const std::vector<int> &v)
{
    size = v.size();

    // compute size of list which will hold the tree
    int h = std::ceil(std::log2(size));
    int n = std::pow(2, h + 1) - 1;

    tree = std::vector<int>(n, std::numeric_limits<int>::min());
    for (int i = 0; i < v.size(); i++)
    {
        Add(i, v[i]);
    }
}

void IntervalTree::Add(int pos, int value)
{
    add(pos, value, 0, 0, size - 1);
}

int IntervalTree::Get(int a, int b) const
{
    return get(a, b, 0, 0, size - 1);
}

void IntervalTree::add(int pos, int value, int i, int l, int r)
{
    if (l == r)
    {
        tree[i] = value;
        return;
    }

    int m = l + (r - l) / 2;
    if (pos <= m)
    {
        add(pos, value, 2 * i + 1, l, m);
    }
    else
    {
        add(pos, value, 2 * i + 2, m + 1, r);
    }

    tree[i] = std::max(tree[2 * i + 1], tree[2 * i + 2]);
}

int IntervalTree::get(int a, int b, int i, int l, int r) const
{
    if (a <= l && r <= b)
    {
        return tree[i];
    }

    int m = l + (r - l) / 2;
    int maxLeft, maxRight;
    maxLeft = a <= m ? get(a, b, 2 * i + 1, l, m) : std::numeric_limits<int>::min();
    maxRight = m < b ? get(a, b, 2 * i + 2, m + 1, r) : std::numeric_limits<int>::min();

    return std::max(maxLeft, maxRight);
}