Cod sursa(job #2282216)

Utilizator veleanduAlex Velea veleandu Data 13 noiembrie 2018 14:47:22
Problema Arbori de intervale Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 2.72 kb
#include <fstream>
using namespace std;

const int kMaxN = 1e5+5;

// Simple and fast segment tree implementation
// The fastest solution to implement for a SIMPLE segment tree
//      mx[node] = max(mx[2 * node], mx[2 * node + 1]);
//  
//      return max(
//          query(2 * node, left, mid, c1, c2),
//          query(2 * node + 1, mid + 1, right, c1, c2)
//      );
// The logic is duplicated and can cause bugs when changing something
// Sometimes the logic can be very difficult (a lot of operations)
// 
// Why a struct?
// - it keeps all the logic in one place.
//      all segment tree related logic is easy to mentain and check
// - with time, this code will become "standard"
//      the majority of the code for the segment tree will be the same every time
//      in this way, it's easy to implement the same segment tree which will be "safe"
//      meaning that it's highly improbable to have bugs or undefined behaviours

struct Aint {
    // 3 * kMaxN is weirdly enough :)
    int mx[3 * kMaxN];

    // Simple single element update
    void update(int node, int left, int right, int pos, int value) {
        // Stop condition
        if (left == right) {
            mx[node] = value;
            return;
        }

        // Advance into the recursion
        int mid = (left + right) / 2;
        if (pos <= mid) {
            update(2 * node, left, mid, pos, value);
        } else {
            update(2 * node + 1, mid + 1, right, pos, value);
        }

        // Make sure the data from the node is correctly computed
        mx[node] = max(mx[2 * node], mx[2 * node + 1]);
    }

    int query(int node, int left, int right, int c1, int c2) {
        // The [left, right] is inside c1 and c2
        // Return the data or update the inverval in case of lazy propagation
        if (c1 <= left and right <= c2) {
            return mx[node];
        }

        // The interval is outside [c1, c2]. No need to go further.
        if (right < c1 or c2 < left) {
            return 0;
        }

        // Return the max of the 2 recursive calls
        int mid = (left + right) / 2;
        return max(
                query(2 * node, left, mid, c1, c2),
                query(2 * node + 1, mid + 1, right, c1, c2)
        );
    }
};

int main() {
    ifstream cin("arbint.in");
    ofstream cout("arbint.out");

    int n, q; cin >> n >> q;

    Aint aint;

    for (int i = 1; i <= n; i += 1) {
        int x; cin >> x;
        aint.update(1, 1, n, i, x);
    }

    while (q--) {
        char c; cin >> c;
        if (c == '0') {
            int a, b; cin >> a >> b;
            cout << aint.query(1, 1, n, a, b) << '\n';
        } else {
            int pos, x; cin >> pos >> x;
            aint.update(1, 1, n, pos, x);
        }
    }

    return 0;
}