Submission #1301063

#TimeUsernameProblemLanguageResultExecution timeMemory
1301063andria_gavObstacles for a Llama (IOI25_obstacles)C++20
10 / 100
99 ms52020 KiB
#include "obstacles.h"
#include <bits/stdc++.h>
using namespace std;

int prnt[200005], cntv[200005];
int fixv[200005], maxtv[200005], maxtn[200005],
    mintv[200005], mintn[200005];
int sparseH[19][200005], sparseA[19][200005], spnomA[19][200005];

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

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

void union_set(int a, int b){
    a = find_set(a);
    b = find_set(b);
    if (a == b) return;
    if (cntv[b] > cntv[a]) swap(a,b);
    cntv[a] += cntv[b];
    prnt[b] = a;
}

int getmaxH(int L, int R){
    int len = R - L + 1;
    int k = 31 - __builtin_clz(len);
    return max(sparseH[k][L], sparseH[k][R+1-(1<<k)]);
}

int getnomA(int L, int R){
    int len = R - L + 1;
    int k = 31 - __builtin_clz(len);
    int n1 = spnomA[k][R+1-(1<<k)];
    int n2 = spnomA[k][L];
    if (sparseA[k][L] > sparseA[k][R+1-(1<<k)]) return n2;
    return n1;
}

void initialize(vector<int> T, vector<int> H){
    int N = T.size(), M = H.size();
    gr.clear();

    for (int i = 0; i < M; i++){
        prnt[i] = i;
        cntv[i] = 1;
        fixv[i] = (H[i] < T[0]);
        sparseA[0][i] = -1;
        sparseH[0][i] = H[i];
        spnomA[0][i] = i;
    }

  
    maxtv[0] = mintv[0] = T[0];
    maxtn[0] = mintn[0] = 0;

    for (int i = 1; i < N; i++){
        maxtv[i] = maxtv[i-1]; maxtn[i] = maxtn[i-1];
        if (T[i] > maxtv[i-1]) maxtv[i] = T[i], maxtn[i] = i;
        mintv[i] = mintv[i-1]; mintn[i] = mintn[i-1];
        if (T[i] < mintv[i-1]) mintv[i] = T[i], mintn[i] = i;
    }

    int nmin = -1, 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 {

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

                int A = 0, B = N - 1;
                while (A < B){
                    int C = (A + B + 1) / 2;
                    if (mintv[C] > hmin) A = C;
                    else B = C - 1;
                }

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

        }
    }

    
    int K = 31 - __builtin_clz(max(1, M));
    for (int k = 1; k <= K; k++){
        int half = 1 << (k - 1);
        for (int i = 0; i + (1<<k) <= M; i++){
            sparseH[k][i] = max(sparseH[k-1][i],
                                sparseH[k-1][i + half]);

            int L = spnomA[k-1][i];
            int R = spnomA[k-1][i + half];

            if (sparseA[k-1][L] >= sparseA[k-1][R]){
                sparseA[k][i] = sparseA[k-1][L];
                spnomA[k][i] = L;
            } else {
                sparseA[k][i] = sparseA[k-1][R];
                spnomA[k][i] = R;
            }
        }
    }

    
    for (int i = 0; i < (int)gr.size(); i++){
        int A = gr[i].A;
        int nom = gr[i].nom;

        int tempT = T[A];
        int bestRow = maxtn[A];

       
        if (i > 0){
            int L = 0, R = nom;
            while (L < R){
                int mid = (L+R)/2;
                if (getmaxH(mid, nom) >= tempT)
                    L = mid + 1;
                else
                    R = mid;
            }
            if (L < nom){
                int x = getnomA(L, nom-1);
                if (sparseA[0][x] >= bestRow) union_set(nom, x);
            }
        }

  
        if (i + 1 < (int)gr.size()){
            int L = nom, R = M - 1;
            while (L < R){
                int mid = (L + R + 1) / 2;
                if (getmaxH(nom, mid) >= tempT)
                    R = mid - 1;
                else
                    L = mid;
            }
            if (L > nom){
                int x = getnomA(nom+1, L);
                if (sparseA[0][x] >= bestRow) union_set(nom, x);
            }
        }
    }
}

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...