Cod sursa(job #1616884)

Utilizator dm1sevenDan Marius dm1seven Data 27 februarie 2016 12:09:32
Problema Arbori de intervale Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 3.32 kb
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <utility>
#include <sstream>
#include <string>
#include <vector>
#include <list>
#include <deque>
#include <map>
#include <set>
#include <stack>
#include <fstream>
#include <chrono>
using namespace std;
using namespace std::chrono;

typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vint;
typedef vector<vint> vvint;
typedef vector<ll> vll;
typedef vector<vll> vvll;
typedef vector<vvll> vvvll;
typedef vector<ull> vull;
typedef vector<vull> vvull;
typedef pair<int, int> pii;
typedef vector<pii> vpii;
typedef pair<ll, ll> pll;
typedef vector<pll> vpll;
typedef vector<string> vstring;

#define fs first
#define sc second
#define pb push_back
// forward strict for, most common
#define fors(i, a, n) for (int i = (int) (a); i < (int) (n); ++i)
// forward inclusive for
#define fori(i, a, n) for (int i = (int) (a); i <= (int) (n); ++i)
// backward for, inclusive
#define forb(i, n, a) for (int i = (int) (n); i >= (a); --i)

class Problem {
public:
    int n;
    int L;
    int m;

    vint arr, tree;

    void solve() {
        ifstream in("arbint.in");
        ofstream out("arbint.out");
        in >> n >> m;
        L = (int) log2(n);
        if ((1 << L) < n) L++;
        arr.resize(n);
        tree.resize(1 << (L + 1));
        
        fors(i, 0, n) in >> arr[i];
        
        // build operation for the entire tree
        update_build_tree(1, 0, n - 1, 0, n - 1, 1);
        
        print_tree();
        
        fors(i, 0, m) {
            int o, u, v;
            in >> o >> u >> v;
            u--; v--;
            if (o == 0) {
                int q = query_tree(1, 0, n - 1, u, v);
                out << q << "\n";
            } else {
                update_build_tree(1, 0, n - 1, u, u, 0, v);
            }
        }
    }
    
    // [a, b] = the range covered by the given node
    // [i, j] = the target interval we want to update/build
    void update_build_tree(int node, int a, int b, int i, int j, int op, int v = 0) {
        if (a > b || a > j || b < i) return; // if completely out of interval [i, j]
        if (a == b) { // if leaf node and inside [i, j]
            if (op == 0) tree[node] = v; // update operation for the range [i, j]
            if (op == 1) tree[node] = arr[a]; // build operation for the range [i, j]
            return;
        }
        int m = (a + b) / 2;
        // left child
        update_build_tree(2*node, a, m, i, j, op, v);
        // right child
        update_build_tree(2*node + 1, m + 1, b, i, j, op, v);
        // join
        tree[node] = max(tree[2*node], tree[2*node + 1]);
    }
    
    int query_tree(int node, int a, int b, int i, int j) {
        if (a > b || a > j || b < i) return -1;
        if (i <= a && b <= j) return tree[node]; // [a, b] totally inside [i, j]
        int m = (a + b) / 2;
        int q1 = query_tree(2*node, a, m, i, j);
        int q2 = query_tree(2 * node + 1, m + 1, b, i, j);
        return max(q1, q2);
    }
    
    void print_tree() {
        fori(l, 0, L) {
            int s = 1 << l, e = 2 * s - 1;
            fori(j, s, e) cout << tree[j] << " ";
            cout << endl;
        }
    }
};

int main() {
    Problem p;
    p.solve();
    return 0;
}