Cod sursa(job #3152426)

Utilizator lucamLuca Mazilescu lucam Data 25 septembrie 2023 03:17:13
Problema Arbori de intervale Scor 0
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.2 kb
#include <bits/stdc++.h>
using namespace std;

#ifdef ONLINE_JUDGE
std::istream &in = std::cin;
std::ostream &out = std::cout;
#else
// std::ifstream in("input.txt");
// std::ostream &out = std::cerr;
#endif

std::ifstream in("arbint.in");
std::ofstream out("arbint.out");

// online/dynamic rmq using segment tree

struct SegTreeState {
    // 4h minus 7
    int n, h;
    array<int, 1 << 18> segtree;

    SegTreeState(int n) : n(n) {
        h = countr_zero(bit_ceil(static_cast<unsigned>(n))) + 1;
        // segtree.resize(1 << h, numeric_limits<int>::min());
        fill_n(segtree.begin(), n, numeric_limits<int>::min());
    }

    void update_point(int i, int x);
    int range_min(int l, int r);

    static inline constexpr int up(int node) {
        return (node - 1) / 2;
    }

    static inline constexpr int down(int node) {
        return node * 2 + 1;
    }

    // the leaves are the last elements of the array
    inline constexpr int idx_from_arr_idx(int i) {
        return i + (1 << (h - 1)) - 1;
    }
};

void SegTreeState::update_point(int i, int x) {
    i = idx_from_arr_idx(i);
    segtree[i] = x;
    // levels start on odd numbers, left is odd
    int j = i - static_cast<int>(i % 2 == 0);
    for (i = up(i); i != -1; i = up(i) - static_cast<int>(i == 0)) {
        segtree[i] = max(segtree[j], segtree[j + 1]);
        j = i - static_cast<int>(i % 2 == 0);
    }
}

struct NodeData {
    pair<int, int> target;
    pair<int, int> limit;
    int idx;
};

inline constexpr bool included_in_2(pair<int, int> p1, pair<int, int> p2) {
    return p2.first <= p1.first && p2.second >= p1.second;
}

int SegTreeState::range_min(int l, int r) {
    queue<NodeData> nodes;
    nodes.push({.target = {l, r}, .limit = {0, (1 << (h - 1)) - 1}, .idx = 0});
    int res = numeric_limits<int>::min();
    while (!nodes.empty()) {
        NodeData u = nodes.front();
        nodes.pop();
        if (included_in_2(u.limit, u.target)) {
            res = max(res, segtree[u.idx]);
            continue;
        }
        int m = midpoint(u.limit.first, u.limit.second);
        // left
        if (u.target.first <= m) {
            nodes.push({
                .target = {u.target.first, u.target.second},
                .limit = {u.limit.first, m},
                .idx = down(u.idx)});
        }
        // right
        if (u.target.second > m) {
            nodes.push({
                .target = {u.target.first, u.target.second},
                .limit = {m + 1, u.limit.second},
                .idx = down(u.idx) + 1});
        }
    }
    return res;
}

enum class Q { Update = 1, RangeMin = 0 };

int main() {
    int n, q;
    in >> n >> q;
    static SegTreeState s(n);
    for (int i = 0; i < n; ++i) {
        int x;
        in >> x;
        if ((i & 1) == 1) {
            s.update_point(i, x);
        }
    }
    for (int i = 0; i < q; ++i) {
        Q query;
        int a, b;
        in >> reinterpret_cast<underlying_type_t<Q> &>(query) >> a >> b;
        switch (query) {
        case Q::Update: {
            s.update_point(a - 1, b);
            break;
        }
        case Q::RangeMin: {
            out << s.range_min(a - 1, b - 1) << "\n";
            break;
        }
        default:
            assert(false);
        }
    }
}