Submission #1329412

#TimeUsernameProblemLanguageResultExecution timeMemory
1329412jochisA Light Inconvenience (CEOI23_light)C++20
5 / 100
201 ms412 KiB
#include "light.h"
#include <vector>
#include <algorithm>
using namespace std;

static long long N;
static vector<long long> lit;

// Construye posiciones canonicas: n, n-1, n-3, n-7, n-15, ... (gaps 2^k - 1)
// Garantiza que la estructura permita alcanzar cualquier nuevo extremo con t <= p
vector<long long> canonical(long long n) {
    vector<long long> res;
    long long gap = 0, pw = 1;
    while (n - gap >= 1 && (int)res.size() < 149) {
        res.push_back(n - gap);
        gap += pw;
        pw *= 2;
    }
    // Asegurar que 1 este incluido
    if (res.empty() || res.back() != 1) {
        if (!res.empty() && res.back() > 1)
            res.push_back(1);
        else if (res.empty())
            res.push_back(1);
    }
    sort(res.begin(), res.end());
    res.erase(unique(res.begin(), res.end()), res.end());
    return res;
}

// Construye intervalos merged de posiciones encendidas despues de spread t
vector<pair<long long,long long>> make_intervals(const vector<long long>& before, long long t, long long n) {
    vector<pair<long long,long long>> intervals;
    for (long long s : before) {
        long long r = min(s + t, n);
        intervals.push_back({s, r});
    }
    sort(intervals.begin(), intervals.end());
    vector<pair<long long,long long>> merged;
    for (auto& iv : intervals) {
        if (!merged.empty() && iv.first <= merged.back().second + 1) {
            merged.back().second = max(merged.back().second, iv.second);
        } else {
            merged.push_back(iv);
        }
    }
    return merged;
}

// Verifica si pos esta en algun intervalo merged (busqueda binaria)
bool in_intervals(const vector<pair<long long,long long>>& ivs, long long pos) {
    int lo = 0, hi = (int)ivs.size() - 1;
    while (lo <= hi) {
        int mid = (lo + hi) / 2;
        if (ivs[mid].second < pos) lo = mid + 1;
        else if (ivs[mid].first > pos) hi = mid - 1;
        else return true;
    }
    return false;
}

void prepare() {
    N = 1;
    lit = {1};
}

pair<long long, vector<long long>> join(long long p) {
    long long new_n = N + p;
    // La antorcha en N alcanza new_n = N+p con t = p <= p_a
    long long t = p;
    N = new_n;

    auto ivs = make_intervals(lit, t, N);
    auto cand = canonical(N);

    vector<long long> result;
    for (long long pos : cand) {
        if (in_intervals(ivs, pos))
            result.push_back(pos);
    }
    // Asegurar que N (extremo derecho) este en el resultado
    if (result.empty() || result.back() != N) {
        result.push_back(N);
        sort(result.begin(), result.end());
        result.erase(unique(result.begin(), result.end()), result.end());
    }

    lit = result;
    return {t, lit};
}

pair<long long, vector<long long>> leave(long long p) {
    long long new_n = N - p;

    // Filtrar antorchas que sobreviven (posicion <= new_n)
    vector<long long> surviving;
    for (long long pos : lit) {
        if (pos <= new_n) surviving.push_back(pos);
    }

    // Calcular t minimo para encender new_n desde la antorcha sobreviviente mas a la derecha
    // Prueba: con estructura canonica, t <= p siempre se cumple
    // La antorcha en N-(2^k-1) con 2^k >= p+1 esta a distancia (2^k-1-p) <= p-1 de new_n
    long long t = 0;
    if (!surviving.empty()) {
        long long rightmost_surv = surviving.back();
        t = new_n - rightmost_surv;
    } else {
        // No deberia ocurrir si siempre guardamos posicion 1
        // Forzar encendido desde 1
        surviving = {1};
        t = new_n - 1;
    }

    N = new_n;

    auto ivs = make_intervals(surviving, t, N);
    auto cand = canonical(N);

    vector<long long> result;
    for (long long pos : cand) {
        if (in_intervals(ivs, pos))
            result.push_back(pos);
    }
    // Asegurar N esta
    if (result.empty() || result.back() != N) {
        result.push_back(N);
        sort(result.begin(), result.end());
        result.erase(unique(result.begin(), result.end()), result.end());
    }

    lit = result;
    return {t, lit};
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...