Submission #1301060

#TimeUsernameProblemLanguageResultExecution timeMemory
1301060andria_gavObstacles for a Llama (IOI25_obstacles)C++20
31 / 100
165 ms52032 KiB
#include "obstacles.h"
#include <bits/stdc++.h>
using namespace std;

int prnt[200005], cnt[200005]; // DSU
int fixv[200005], maxt[200005], maxt_n[200005],
    mintt[200005], mint_n[200005];
int sparseH[19][200005], sparseA[19][200005], spnomA[19][200005];

struct Hval { int h, ind; };
bool operator <(Hval a, Hval b){ return a.h < b.h; }
bool operator ==(Hval a, Hval b){ return a.h == b.h; }

struct Gr { int A, nom; };
vector<Gr> gr;
Gr tmp;

int find_set(int u){
    if (prnt[u] != u) prnt[u] = find_set(prnt[u]);
    return prnt[u];
}

void union_set(int u, int v){
    u = find_set(u); 
    v = find_set(v);
    if (u == v) return;

    if (cnt[v] > cnt[u]) swap(u, v);
    cnt[u] += cnt[v];
    prnt[v] = u;
}

int getmaxH(int a, int b){
    int len = b - a + 1;
    if (len == 1) return sparseH[0][a];
    int k = log2(len);
    return max(sparseH[k][a], sparseH[k][b + 1 - (1 << k)]);
}

int getnomA(int a, int b){
    int len = b - a + 1;
    if (len == 1) return spnomA[0][a];
    int k = log2(len);
    int nom = spnomA[k][b + 1 - (1 << k)];
    if (sparseA[k][a] > sparseA[k][b + 1 - (1 << k)])
        nom = spnomA[k][a];
    return nom;
}

void initialize(std::vector<int> T, std::vector<int> H) {

    int n = T.size(), m = H.size();
    gr.clear();

    for (int i = 0; i < m; i++){
        prnt[i] = i;
        cnt[i] = 1;

        fixv[i] = (H[i] < T[0] ? 1 : 0);

        sparseA[0][i] = -1;
        sparseH[0][i] = H[i];
        spnomA[0][i] = i;
    }

    // prefix max/min T
    maxt[0] = T[0]; maxt_n[0] = 0;
    mintt[0] = T[0]; mint_n[0] = 0;

    for (int i = 1; i < n; i++){
        maxt[i] = maxt[i-1];
        maxt_n[i] = maxt_n[i-1];
        if (T[i] > maxt[i-1]){
            maxt[i] = T[i];
            maxt_n[i] = i;
        }

        mintt[i] = mintt[i-1];
        mint_n[i] = mint_n[i-1];
        if (T[i] < mintt[i-1]){
            mintt[i] = T[i];
            mint_n[i] = i;
        }
    }

    int nmin = -1;
    int hmin = 1e9 + 5;

    if (fixv[0]) {
        nmin = 0;
        hmin = H[0];
    }

    for (int i = 1; i < m; i++){  

        if (fixv[i]){

            if (fixv[i-1]) {
                union_set(i, i-1);
                if (H[i] < hmin)
                    hmin = H[i], nmin = i;
            }
            else {
                hmin = H[i];
                nmin = i;
            }

        } 
        else { // fixv[i] == 0

            if (fixv[i-1] && nmin != -1) {

                int A = 0, B = n - 1, C;

                while (A < B){
                    C = (A + B + 1) / 2;
                    if (mintt[C] > hmin) A = C;
                    else B = C - 1;
                }

                if (A > 0){
                    tmp.A = A;
                    tmp.nom = nmin;
                    gr.push_back(tmp);
                    sparseA[0][nmin] = A;
                }
            }
        }
    }

    int k = log2(max(1, m));
    for (int lvl = 1; lvl <= k; lvl++){
        int len2 = 1 << (lvl - 1);
        int len = 1 << lvl;
        for (int j = 0; j + len <= m; j++){
            sparseH[lvl][j] = max(sparseH[lvl-1][j],
                                  sparseH[lvl-1][j + len2]);

            sparseA[lvl][j] = sparseA[lvl-1][j + len2];
            spnomA[lvl][j] = spnomA[lvl-1][j + len2];

            if (sparseA[lvl-1][j] > sparseA[lvl-1][j + len2]){
                sparseA[lvl][j] = sparseA[lvl-1][j];
                spnomA[lvl][j] = spnomA[lvl-1][j];
            }
        }
    }

    for (int i = 0; i < (int)gr.size(); i++){

        int Apos = gr[i].A;
        int nom = gr[i].nom;

        int temp = T[Apos];
        int height = maxt_n[Apos];

        // left
        if (i > 0){
            int A = 0, B = nom, C;
            while (A < B){
                C = (A + B) / 2;
                int maxh = getmaxH(C, nom);
                if (maxh >= temp) A = C + 1;
                else B = C;
            }
            if (A < nom){
                int nom2 = getnomA(A, nom - 1);
                if (sparseA[0][nom2] >= height)
                    union_set(nom, nom2);
            }
        }

        // right
        if (i + 1 < (int)gr.size()){
            int A = nom, B = m - 1, C;
            while (A < B){
                C = (A + B + 1) / 2;
                int maxh = getmaxH(nom, C);
                if (maxh >= temp) B = C - 1;
                else A = C;
            }
            if (A > nom){
                int nom2 = getnomA(nom + 1, A);
                if (sparseA[0][nom2] >= height)
                    union_set(nom, nom2);
            }
        }
    }
}

bool can_reach(int L, int R, int S, int D) {
    
    return find_set(S) == find_set(D);
}
#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...