제출 #1339563

#제출 시각아이디문제언어결과실행 시간메모리
1339563lucas110550장애물 (IOI25_obstacles)C++20
83 / 100
135 ms19936 KiB
#include <bits/stdc++.h>
using namespace std;

/* ------------------------------------------------------------------ */
/*  Disjoint Set Union (Union–Find)                                   */
/* ------------------------------------------------------------------ */
struct DSU {
    vector<int> parent, sz;
    DSU(int n = 0) { init(n); }

    void init(int n) {
        parent.resize(n);
        sz.assign(n, 1);
        iota(parent.begin(), parent.end(), 0);
    }

    int find(int x) {
        while (parent[x] != x) {
            parent[x] = parent[parent[x]];
            x = parent[x];
        }
        return x;
    }

    void union_sets(int a, int b) {
        a = find(a);
        b = find(b);
        if (a == b) return;
        if (sz[a] < sz[b]) swap(a, b);
        parent[b] = a;
        sz[a] += sz[b];
    }
};

/* ------------------------------------------------------------------ */
/*  Segment tree for range maximum (static)                           */
/* ------------------------------------------------------------------ */
struct MaxSegTree {
    int n;          // original size
    int size;       // power of two >= n
    vector<int> tree;   // 2*size elements

    MaxSegTree() : n(0), size(0) {}

    explicit MaxSegTree(const vector<int>& data) {
        build(data);
    }

    void build(const vector<int>& data) {
        n = static_cast<int>(data.size());
        size = 1;
        while (size < n) size <<= 1;
        tree.assign(2 * size, 0);
        for (int i = 0; i < n; ++i) tree[size + i] = data[i];
        for (int i = size - 1; i > 0; --i)
            tree[i] = max(tree[i << 1], tree[i << 1 | 1]);
    }

    // inclusive query [l, r]; returns -1 for empty interval
    int query(int l, int r) const {
        if (l > r) return -1;
        l += size; r += size;
        int res = -1;
        while (l <= r) {
            if (l & 1)  res = max(res, tree[l++]);
            if (!(r & 1)) res = max(res, tree[r--]);
            l >>= 1; r >>= 1;
        }
        return res;
    }
};

/* ------------------------------------------------------------------ */
/*  Segment tree that stores min / max *active* column indices         */
/* ------------------------------------------------------------------ */
struct ActiveSegTree {
    int n;                 // number of columns
    int size;              // power of two >= n
    vector<int> max_tree; // maximum active index inside the node
    vector<int> min_tree; // minimum active index inside the node

    explicit ActiveSegTree(int n_) : n(n_) {
        size = 1;
        while (size < n) size <<= 1;
        max_tree.assign(2 * size, -1);
        min_tree.assign(2 * size, n);
    }

    // mark column idx as active
    void activate(int idx) {
        int i = idx + size;
        max_tree[i] = idx;
        min_tree[i] = idx;
        for (i >>= 1; i; i >>= 1) {
            int left  = i << 1;
            int right = left | 1;
            max_tree[i] = max(max_tree[left], max_tree[right]);
            min_tree[i] = min(min_tree[left], min_tree[right]);
        }
    }

    // maximum active index in [l, r]; -1 if none
    int query_max(int l, int r) const {
        if (l > r) return -1;
        l += size; r += size;
        int res = -1;
        while (l <= r) {
            if (l & 1)  res = max(res, max_tree[l++]);
            if (!(r & 1)) res = max(res, max_tree[r--]);
            l >>= 1; r >>= 1;
        }
        return res;
    }

    // minimum active index in [l, r]; n if none
    int query_min(int l, int r) const {
        if (l > r) return n;
        l += size; r += size;
        int res = n;
        while (l <= r) {
            if (l & 1)  res = min(res, min_tree[l++]);
            if (!(r & 1)) res = min(res, min_tree[r--]);
            l >>= 1; r >>= 1;
        }
        return res;
    }
};

/* ------------------------------------------------------------------ */
/*  Global data (mirrors the Python module)                           */
/* ------------------------------------------------------------------ */
int N = 0, M = 0;
vector<int> pref_max;   // prefix maximum of T, length N
vector<int> comp;       // component id for each column
DSU* dsu = nullptr;     // created inside initialize

/* ------------------------------------------------------------------ */
/*  Interface required by the statement                                 */
/* ------------------------------------------------------------------ */
void initialize(vector<int> T, vector<int> H)
{
    N = static_cast<int>(T.size());
    M = static_cast<int>(H.size());

    /* 1. prefix maximum of temperatures */
    pref_max.assign(N, 0);
    pref_max[0] = T[0];
    for (int i = 1; i < N; ++i)
        pref_max[i] = max(pref_max[i-1], T[i]);

    /* 2. first blocked row for every column */
    vector<int> col_by_h(M);
    iota(col_by_h.begin(), col_by_h.end(), 0);
    sort(col_by_h.begin(), col_by_h.end(),
         [&](int a, int b){ return H[a] > H[b]; });

    vector<int> first_block(M, N);
    int ptr = 0;
    for (int i = 0; i < N; ++i) {
        int ti = T[i];
        while (ptr < M && H[col_by_h[ptr]] >= ti) {
            int col = col_by_h[ptr];
            first_block[col] = i;
            ++ptr;
        }
    }

    vector<int> Lcol(M);
    for (int j = 0; j < M; ++j) {
        if (first_block[j] == N) Lcol[j] = N - 1;
        else                     Lcol[j] = first_block[j] - 1;
    }

    /* 3. V[j] = max temperature in rows 0 … Lcol[j] */
    vector<int> V(M);
    for (int j = 0; j < M; ++j) {
        if (Lcol[j] >= 0) V[j] = pref_max[Lcol[j]];
        else               V[j] = -1;          // column can never be reached
    }

    /* 4. segment tree for range maximum of humidity (static) */
    MaxSegTree seg_H(H);

    /* 5. DSU over columns */
    dsu = new DSU(M);

    /* 6. process columns in decreasing V */
    vector<int> order(M);
    iota(order.begin(), order.end(), 0);
    sort(order.begin(), order.end(),
         [&](int a, int b){ return V[a] > V[b]; });

    ActiveSegTree active_seg(M);   // no column active at the beginning

    for (int col : order) {
        int vcol = V[col];
        active_seg.activate(col);               // make the column active

        // ---- left neighbour ----
        int left = -1;
        if (col > 0) left = active_seg.query_max(0, col - 1);
        if (left != -1) {
            int max_h = seg_H.query(left, col);
            if (max_h < vcol) dsu->union_sets(col, left);
        }

        // ---- right neighbour ----
        int right = M;
        if (col + 1 < M) right = active_seg.query_min(col + 1, M - 1);
        if (right != M) {
            int max_h = seg_H.query(col, right);
            if (max_h < vcol) dsu->union_sets(col, right);
        }
    }

    /* 7. store the component id for every column */
    comp.resize(M);
    for (int i = 0; i < M; ++i) comp[i] = dsu->find(i);
}

bool can_reach(int L, int R, int S, int D)
{
    (void)L; (void)R;          // unused, required by the signature
    return comp[S] == comp[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...