Submission #1256264

#TimeUsernameProblemLanguageResultExecution timeMemory
1256264nibertObstacles for a Llama (IOI25_obstacles)C++20
10 / 100
65 ms17480 KiB
#include <bits/stdc++.h>
using namespace std;

struct DSU {
    vector<int> p, sz;
    DSU(int n): p(n), sz(n,1) { iota(p.begin(), p.end(), 0); }
    int find(int x){ return p[x]==x?x:p[x]=find(p[x]); }
    void unite(int a,int b){
        a=find(a); b=find(b);
        if(a==b) return;
        if(sz[a]<sz[b]) swap(a,b);
        p[b]=a; sz[a]+=sz[b];
    }
};

int N,M;
vector<int> T,H;
vector<int> linkRight; // linkRight[c] = furthest column reachable from col c in row 0
vector<int> maxReach;  // prefix max of linkRight

inline int id(int i,int j){ return i*M + j; }

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

    // Step 1: mark free cells
    vector<char> freecell((long long)N * M, 0);
    for(int i=0;i<N;i++){
        for(int j=0;j<M;j++){
            if(T[i] > H[j]) freecell[id(i,j)] = 1;
        }
    }

    // Step 2: build DSU for all free cells
    DSU dsu(N*M);
    // vertical edges
    for(int i=0;i<N-1;i++){
        for(int j=0;j<M;j++){
            if(freecell[id(i,j)] && freecell[id(i+1,j)])
                dsu.unite(id(i,j), id(i+1,j));
        }
    }
    // horizontal edges
    for(int i=0;i<N;i++){
        for(int j=0;j<M-1;j++){
            if(freecell[id(i,j)] && freecell[id(i,j+1)])
                dsu.unite(id(i,j), id(i,j+1));
        }
    }

    // Step 3: For each component touching row 0, find min & max column in row 0
    vector<int> minCol(N*M, M), maxCol(N*M, -1);
    for(int j=0;j<M;j++){
        if(freecell[id(0,j)]){
            int root = dsu.find(id(0,j));
            minCol[root] = min(minCol[root], j);
            maxCol[root] = max(maxCol[root], j);
        }
    }

    // Step 4: Build linkRight for each col in row 0
    linkRight.assign(M, -1);
    for(int j=0;j<M;j++){
        if(freecell[id(0,j)]){
            int root = dsu.find(id(0,j));
            linkRight[j] = maxCol[root];
        } else {
            linkRight[j] = j; // blocked cell: can only "reach" itself
        }
    }

    // Step 5: Build prefix maxReach
    maxReach.assign(M, -1);
    int curMax = -1;
    for(int j=0;j<M;j++){
        curMax = max(curMax, linkRight[j]);
        maxReach[j] = curMax;
    }
}

bool can_reach(int L, int R, int S, int D) {
    if(S > D) swap(S,D);
    // Check both start & end are free
    if(maxReach[S] < S || maxReach[D] < D) return false; // blocked cells
    // Check if reachable without leaving [L,R]
    if(S < L || D > R) return false;
    // The precomputed maxReach must cover D within [L,R]
    return maxReach[S] >= 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...