Cod sursa(job #3187048)

Utilizator tamionvTamio Vesa Nakajima tamionv Data 27 decembrie 2023 08:59:23
Problema Arbori de intervale Scor 100
Compilator cpp-64 Status done
Runda Arhiva educationala Marime 3.33 kb
#include <algorithm>
#include <cstdio>
#include <iostream>
using namespace std;

constexpr unsigned maxn = 1 << 17;

namespace {
template <unsigned niv>
unsigned buf[niv];

template <unsigned niv = maxn>
void build() {
    if constexpr (niv > 1) {
#pragma GCC unroll 128
        for (unsigned i = 0; i < niv; i += 2)
            buf<niv / 2>[i / 2] = max(buf<niv>[i], buf<niv>[i + 1]);
        build<niv / 2>();
    }
}

namespace for_rebuild {
int i, j;

template <unsigned niv>
void rebuildj();

template <unsigned niv>
void rebuildi() {
    if constexpr (niv > 1) {
        buf<niv / 2>[j] = max(buf<niv>[i], buf<niv>[i ^ 1]);
        i = j / 2;
        rebuildj<niv / 2>();
    }
}

template <unsigned niv>
void rebuildj() {
    if constexpr (niv > 1) {
        buf<niv / 2>[i] = max(buf<niv>[j], buf<niv>[j ^ 1]);
        j = i / 2;
        rebuildi<niv / 2>();
    }
}
}  // namespace for_rebuild

void update(unsigned i, unsigned x) {
    buf<maxn>[i] = x;
    for_rebuild::i = i;
    for_rebuild::j = i / 2;

    for_rebuild::rebuildi<maxn>();
}

namespace for_query {
unsigned st, dr, r;

template <unsigned niv = maxn>
void _query() {
    if constexpr (niv >= 1) {
        if (st == dr) return;
        if (st % 2) r = max(r, buf<niv>[st++]);
        if (dr % 2) r = max(r, buf<niv>[--dr]);
        st /= 2;
        dr /= 2;
        _query<niv / 2>();
    }
}
}  // namespace for_query

unsigned query(unsigned a, unsigned b) {
    for_query::st = a, for_query::dr = b, for_query::r = 0;
    for_query::_query();
    return for_query::r;
}

constexpr int maxbuf = 2e6 + 100;
char rdbuf[maxbuf] = {}, *ip = rdbuf;

char getch() {
    if (*ip < '0') {
        ++ip;
        if (*ip < '0') ++ip;
    }
    return *ip++;
}

unsigned get_int() {
    unsigned x = 0;
    if (*ip < '0') {
        ++ip;
        if (*ip < '0') ++ip;
    }
    for (; *ip >= '0'; ++ip) x = 10 * x + *ip - '0';
    return x;
}

// Thanks to:
// https://stackoverflow.com/questions/25892665/performance-of-log10-function-returning-an-int
unsigned digits(unsigned x) {
    static constexpr unsigned char guess[33] = {
        0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4,
        5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 8, 8, 8, 9, 9, 9};
    static constexpr unsigned int tenToThe[] = {
        1,      10,      100,      1000,      10000,
        100000, 1000000, 10000000, 100000000, 1000000000,
    };
    unsigned int digits = guess[32 - __builtin_clz(x)];
    return digits + (x >= tenToThe[digits]);
}

char wrbuf[maxbuf], *op = wrbuf;
void write_int(int x) {
    if (x < 10) {
        *op++ = '0' + x;
        *op++ = '\n';
    } else {
        char *p = (op += digits(x));
        for (int y; x;) {
            y = x / 10;
            *--p = x - 10 * y + '0';
            if (y) {
                x = y / 10;
                *--p = y - 10 * x + '0';
            } else
                break;
        }
        *op++ = '\n';
    }
}
};  // namespace

unsigned n, q, a, b;
char t;

int main() {
    fread(rdbuf, sizeof(char), maxbuf, fopen("arbint.in", "r"));

    n = get_int(), q = get_int();

    for (unsigned i = 0; i < n; ++i) buf<maxn>[i] = get_int();

    build();

    while (q--) {
        t = getch(), a = get_int(), b = get_int();
        if (t == '1')
            update(a - 1, b);
        else
            write_int(query(a - 1, b));
    }

    fwrite(wrbuf, sizeof(char), op - wrbuf, fopen("arbint.out", "w"));
}