Cod sursa(job #1972540)

Utilizator andreipnAndrei Petre andreipn Data 23 aprilie 2017 12:39:54
Problema Arbori de intervale Scor 50
Compilator cpp Status done
Runda Arhiva educationala Marime 4.73 kb
// http://www.infoarena.ro/problema/arbint

//#define DEBUG 1

#include <fstream>

#ifndef __SEGTREE__H__
#define __SEGTREE__H__

#include <assert.h>
#include <cmath>
#include <iostream>
#include <queue>

#define MIN(a,b)        ((a) < (b) ? (a) : (b))
#define MAX(a,b)        ((a) > (b) ? (a) : (b))

#define OP(a,b)        ((a) > (b) ? (a) : (b))

#define LEFT(i)         (2*(i)+1)
#define RIGHT(i)        (2*(i)+2)
#define PARENT(i)       ((i-1)/2)


using namespace std;

template <typename T>
struct Node {
    // indices
    int left, right;
    // cached results of subtrees
    T value;

    Node() : left(-1), right(-1), value(T()) {}

    Node(int left, int right, T value): left(left), right(right), value(value) {}

    friend ostream& operator<<(ostream& out, Node& n) {
        out << "[" << n.left << ", " << n.right << "], op = " << n.value << "\n";
        return out;
    }
};

#define MAXN 100000

template <typename T>
class SegTree {
    Node<T> elems[4*MAXN];
    int n;
    int input_size;

public:
    SegTree(T *input, int input_size) {
        this->input_size = input_size;

        //int height = ceil(log2(this->input_size));
        //n = pow(2, height+1);

        //elems = new Node<T>[n];

        build(0, 0, input_size - 1, input);
    }

    ~SegTree() {
        //delete[] elems;
    }

    T query(int start, int end) {
#ifdef DEBUG
        cout << "Query(" << start <<"," << end << ")\n";
#endif

        return do_query(start, end, 0);
    }

    void update(int index, T new_val) {
        if (index < 0 || index >= input_size)
            return;

#ifdef DEBUG
        cout << "update tree[" << index << "] = " << new_val << "\n";
#endif
        int i = 0;
        for(;;) {
            if (elems[i].left == index)
                break;
            if (elems[LEFT(i)].right >= index)
                i = LEFT(i);
            else
                i = RIGHT(i);
        }
#ifdef DEBUG
        cout << "Found position " << i << "for index " << index << "\n";
#endif

        // go to leaf node that has [index, index]
        while (elems[i].left != elems[i].right)
            i = LEFT(i);
        assert(elems[i].left == index);

        elems[i].value = new_val;

        while (i) {
            elems[PARENT(i)].value = OP(
                elems[LEFT(PARENT(i))].value,
                elems[RIGHT(PARENT(i))].value
            );
            i = PARENT(i);
        }
    }

    friend ostream& operator<<(ostream &out, const SegTree& t) {
        // do BFS on tree to print it in expected order.
        queue<int> Q;
        Q.push(0);
        while (!Q.empty()) {
            int index = Q.front();
            Q.pop();

            Node<T> n = t.elems[index];

            out << index << " - " << n << " ";

            if (n.left != n.right) {
                Q.push(LEFT(index));
                Q.push(RIGHT(index));
            }
        }
        out << "\n";

        return out;
    }

private:
    T do_query(int start, int end, int i) {
        start = MAX(start, elems[i].left);
        end = MIN(end, elems[i].right);

        assert(start <= end);
        if (start == elems[i].left && end == elems[i].right)
            return elems[i].value;

        if (end <= elems[LEFT(i)].right)
            return do_query(start, end, LEFT(i));
        else if (start >= elems[RIGHT(i)].left)
            return do_query(start, end, RIGHT(i));
        else
            return OP(
                do_query(start, end, LEFT(i)),
                do_query(start, end, RIGHT(i))
            );
    }

    void build(int idx, int left, int right, T *input) {
        assert (left <= right);
        T value;
        if (left == right) {
            value = input[left];
        } else {
            int mid = (right+left)/2;
            build(LEFT(idx), left, mid, input);
            build(RIGHT(idx), mid+1, right, input);
            value = OP(elems[LEFT(idx)].value,
                       elems[RIGHT(idx)].value);
        }
        Node<T> x(left, right, value);
        elems[idx] = x;
    }
};

#endif

using namespace std;

int main() {
    int n, m, op, a, b;
    ifstream infile("arbint.in");
    ofstream outfile("arbint.out");

    infile >> n >> m;

#ifdef DEBUG
    cout << n << " " << m << "\n";
#endif

    int A[n];
    for (int i = 0; i < n; ++i)
        infile >> A[i];

    SegTree<int> tree(A, n);

#ifdef DEBUG
    cout << tree;
#endif

    for (int i = 0; i < m; ++i) {
        infile >> op >> a >> b;

        if (op == 0) {
            a--; b--;
            int o = tree.query(a, b);
#ifdef DEBUG
            cout << o << "\n";
#endif
            outfile << o << "\n";
        } else if (op == 1) {
            a--;
            tree.update(a, b);
        } else {
#ifdef DEBUG
            cout << "Unknown operation " << op << "\n";
#endif
        }
    }

    return 0;
}