Cod sursa(job #1276831)

Utilizator gabrieligabrieli gabrieli Data 26 noiembrie 2014 21:43:12
Problema Arbori de intervale Scor 100
Compilator cpp Status done
Runda Arhiva educationala Marime 2.78 kb
#include <fstream>
#include <memory>
#include <limits>
#include <algorithm>
#include <vector>
#include <iterator>

using namespace std;

const int INF = std::numeric_limits<int>::max();

struct Node
{
    int v;
    shared_ptr<Node> left;
    shared_ptr<Node> right;
    
    Node(int v = -INF, shared_ptr<Node> left = nullptr, shared_ptr<Node> right = nullptr)
    : v {v}, left {left}, right {right}
    {} 
};

class IntervalTree
{
public:
    IntervalTree(const vector<int>& V)
    : root {make_shared<Node>()}, size {V.size()}
    {
        make_tree(root, 0, size - 1, V);
    }
    
    void update(int value, int position)
    {
        update(root, value, position, 0, size - 1);
    }
    
    int findMax(int left, int right)
    {
        return find(root, 0, size - 1, left, right);
    }
    
private:
    static void make_tree(
            shared_ptr<Node> node,
            int begin, int end,
            const vector<int>& V)
    {
        if (begin == end)
        {
            node->v = V[begin];
            return;
        }
        
        int middle = begin + (end - begin) / 2;
        
        node->left = make_shared<Node>();
        make_tree(node->left, begin, middle, V);
        
        node->right = make_shared<Node>();
        make_tree(node->right, middle + 1, end, V);
        
        node->v = max(node->left->v, node->right->v);
    }

    void update(shared_ptr<Node> node, int v, int pos, int begin, int end)
    {
        if (begin == end)
        {
            node->v = v;
            return;
        }
        
        int middle = begin + (end - begin) / 2;
        if (pos <= middle)
            update(node->left, v, pos, begin, middle);
        else
            update(node->right, v, pos, middle + 1, end);
            
        node->v = max(node->left->v, node->right->v);
    }

    int find(shared_ptr<Node> node, int begin, int end, int l, int r) const
    {
        if (l <= begin && end <= r)
            return node->v;
        
        int middle = begin + (end - begin) / 2;
        int u = -INF, v = -INF;
        if (l <= middle)
            u = find(node->left, begin, middle, max(l, begin), min(r, middle));
        if (middle < r)
            v = find(node->right, middle + 1, end, max(middle + 1, l), min(r, end));
        
        return max(u, v);
    }
    
private:
    shared_ptr<Node> root;
    int size;
};

int main()
{
    std::ifstream fin("arbint.in");
    std::ofstream fout("arbint.out");
    
    int n, m;
    fin >> n >> m;
    
    vector<int> V;
    copy_n(istream_iterator<int>(fin), n, back_inserter(V));
    
    IntervalTree tree(V);   
    for (int q, a, b; m; --m)
    {
        fin >> q >> a >> b;
        
        if (q == 0)
            fout << tree.findMax(--a, --b) << '\n';
        else
            tree.update(b, --a);
    }
    
    return 0;
}