Cod sursa(job #2865496)

Utilizator the_horoHorodniceanu Andrei the_horo Data 8 martie 2022 21:07:57
Problema Arbori de intervale Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 4.37 kb
#include <algorithm>
#include <array>
#include <cstdint>
#include <fstream>
#include <tuple>
#include <vector>


/* Defines */
using i32 = int32_t;
using u32 = uint32_t;

using Position = std::tuple<size_t, size_t, size_t>;

constexpr const char *inputFilename = "arbint.in";
constexpr const char *outputFilename = "arbint.out";

constexpr size_t MAX_NUMBERS = 100000;


/* Function definitions */
Position left(Position p);
Position right(Position p);

size_t intLeft(Position p);
size_t intRight(Position p);
size_t node(Position p);
size_t mid(Position p);

void build(const std::vector<u32> &values, Position position);
u32 query(size_t left, size_t right, Position position);
void update(size_t index, u32 value, Position position);

void printArbint(Position position);
void printPosition(Position position);

/* Global variables */
std::array<u32, MAX_NUMBERS * 4> arbint;


/* Functoin declarations */
Position left (Position p) {
    return {
        std::get<0>(p) * 2 + 1,
        std::get<1>(p),
        mid(p)
    };
}

Position right (Position p) {
    return {
        std::get<0>(p) * 2 + 2,
        mid(p),
        std::get<2>(p)
    };
}

size_t intLeft  (Position p) { return std::get<1>(p); }
size_t intRight (Position p) { return std::get<2>(p); }
size_t node  (Position p) { return std::get<0>(p); }
size_t mid (Position p) { return intLeft(p) + (intRight(p) - intLeft(p)) / 2; }

void build (const std::vector<u32>& values, Position position) {
    if (intLeft(position) + 1 == intRight(position)) {
        arbint[node(position)] = values[intLeft(position)];
        return;
    }

    if (intLeft(position) >= intRight(position))
        return;

    build(values, left(position));
    build(values, right(position));

    arbint[node(position)] = std::max(arbint[node(left(position))], arbint[node(right(position))]);
}

u32 query (size_t qLeft, size_t qRight, Position position) {
    if (qLeft <= intLeft(position) && intRight(position) <= qRight)
        return arbint[node(position)];

    if (qRight <= intLeft(position) || qLeft >= intRight(position))
        return 0;

    if (intLeft(position) == intRight(position))
        return 0;

    u32 max = 0;
    const size_t mij = mid(position);

    if (qLeft < mij)
        max = std::max(max, query(qLeft, qRight, left(position)));

    if (mij < qRight)
        max = std::max(max, query(qLeft, qRight, right(position)));

    return max;
}

void update (size_t index, u32 value, Position position) {
    if (intLeft(position) == intRight(position) - 1 && intLeft(position) == index) {
        arbint[node(position)] = value;
        return;
    }

    const size_t mij = mid(position);

    if (index < mij)
        update(index, value, left(position));
    if (mij <= index)
        update(index, value, right(position));

    arbint[node(position)] = std::max(arbint[node(left(position))], arbint[node(right(position))]);
}

void printArbint (Position position) {
    if (intLeft(position) >= intRight(position))
        return;

    std::fprintf(stderr, "For interval [%zu, %zu) the maximum is %u\n", intLeft(position), intRight(position), arbint[node(position)]);
    std::fflush(stderr);

    if (intLeft(position) != intRight(position) - 1) {
        printArbint(left(position));
        printArbint(right(position));
    }
}

void printPosition (Position p) {
    std::fprintf(stderr, "Position with left: %zu, right: %zu, node: %zu, maximum associated: %u\n", intLeft(p), intRight(p), node(p), arbint[node(p)]);
    std::fflush(stderr);
}

int main () {
    std::ifstream input(inputFilename);
    input.exceptions(input.badbit | input.eofbit | input.failbit);
    std::ofstream output(outputFilename);
    output.exceptions(output.badbit | output.eofbit | output.failbit);

    size_t valueCount;
    u32 queries;
    input >> valueCount >> queries;

    std::vector<u32> values(valueCount);
    for (auto &value: values)
        input >> value;

    const Position startPosition = {0, 0, valueCount};

    build(values, startPosition);

    for (u32 q = 0; q != queries; ++ q) {
        u32 type;
        input >> type;

        if (type == 0) {
            size_t left, right;
            input >> left >> right;

            output << query(left - 1, right, startPosition);
            output.put('\n');
        } else {
            size_t index;
            u32 value;
            input >> index >> value;

            update(index - 1, value, startPosition);
        }
    }
}