제출 #1274818

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

struct SegTree {
    struct Node {
        int mx;          // maximum H in the segment
        int mn;          // minimum H in the segment
        int mnPos;       // position of the minimum (any)
    };
    int n;
    vector<Node> st;
    vector<int> *arrPtr; // pointer to original H array

    SegTree() : n(0), arrPtr(nullptr) {}

    void init(const vector<int> &arr) {
        n = (int)arr.size();
        arrPtr = const_cast<vector<int>*>(&arr);
        st.assign(4 * n, Node());
        build(1, 0, n - 1);
    }

    void build(int p, int l, int r) {
        if (l == r) {
            int val = (*arrPtr)[l];
            st[p] = {val, val, l};
            return;
        }
        int m = (l + r) >> 1;
        build(p << 1, l, m);
        build(p << 1 | 1, m + 1, r);
        pull(p);
    }

    void pull(int p) {
        const Node &L = st[p << 1];
        const Node &R = st[p << 1 | 1];
        st[p].mx = max(L.mx, R.mx);
        if (L.mn <= R.mn) {
            st[p].mn = L.mn;
            st[p].mnPos = L.mnPos;
        } else {
            st[p].mn = R.mn;
            st[p].mnPos = R.mnPos;
        }
    }

    // range minimum query (value, position)
    pair<int,int> queryMin(int p, int l, int r, int ql, int qr) const {
        if (qr < l || ql > r) return {INT_MAX, -1};
        if (ql <= l && r <= qr) return {st[p].mn, st[p].mnPos};
        int m = (l + r) >> 1;
        auto left = queryMin(p<<1, l, m, ql, qr);
        auto right = queryMin(p<<1|1, m+1, r, ql, qr);
        if (left.first <= right.first) return left;
        return right;
    }

    // public wrapper
    pair<int,int> rangeMin(int l, int r) const {
        return queryMin(1, 0, n-1, l, r);
    }

    // find first index in [ql,qr] where H >= thr, returns n if none
    int findFirstGE(int p, int l, int r, int ql, int qr, int thr) const {
        if (qr < l || ql > r) return n;
        if (st[p].mx < thr) return n;
        if (l == r) return l;
        int m = (l + r) >> 1;
        int leftRes = findFirstGE(p<<1, l, m, ql, qr, thr);
        if (leftRes != n) return leftRes;
        return findFirstGE(p<<1|1, m+1, r, ql, qr, thr);
    }

    // find last index in [ql,qr] where H >= thr, returns -1 if none
    int findLastGE(int p, int l, int r, int ql, int qr, int thr) const {
        if (qr < l || ql > r) return -1;
        if (st[p].mx < thr) return -1;
        if (l == r) return l;
        int m = (l + r) >> 1;
        int rightRes = findLastGE(p<<1|1, m+1, r, ql, qr, thr);
        if (rightRes != -1) return rightRes;
        return findLastGE(p<<1, l, m, ql, qr, thr);
    }

    // wrappers
    int firstGE(int l, int r, int thr) const {
        if (l > r) return n;
        return findFirstGE(1, 0, n-1, l, r, thr);
    }
    int lastGE(int l, int r, int thr) const {
        if (l > r) return -1;
        return findLastGE(1, 0, n-1, l, r, thr);
    }
};

static vector<int> T_global;
static vector<int> H_global;
static vector<int> prefMaxT;
static SegTree seg;
static int N, M;

// compute deepest reachable row index starting from a given column position
static int computeDepth(int startPos) {
    int curPos = startPos;
    int curMin = H_global[curPos];
    int depth = 0;                 // row 0 is always reachable
    for (int i = 1; i < N; ++i) {
        if (T_global[i] <= curMin) break;   // cannot go down to this row
        // expand the horizontal interval on row i starting from curPos
        int leftBound = 0;
        if (curPos > 0) {
            int leftBlock = seg.lastGE(0, curPos - 1, T_global[i]);
            if (leftBlock != -1) leftBound = leftBlock + 1;
        }
        int rightBound = M - 1;
        if (curPos < M - 1) {
            int rightBlock = seg.firstGE(curPos + 1, M - 1, T_global[i]);
            if (rightBlock != M) rightBound = rightBlock - 1;
        }
        // query the minimum humidity inside the new interval
        auto minInfo = seg.rangeMin(leftBound, rightBound);
        curPos = minInfo.second;
        curMin = minInfo.first;
        depth = i;
    }
    return depth;
}

void initialize(vector<int> T, vector<int> H) {
    T_global.swap(T);
    H_global.swap(H);
    N = (int)T_global.size();
    M = (int)H_global.size();

    prefMaxT.resize(N);
    for (int i = 0; i < N; ++i) {
        prefMaxT[i] = (i == 0) ? T_global[0] : max(prefMaxT[i-1], T_global[i]);
    }
    seg.init(H_global);
}

bool can_reach(int L, int R, int S, int D) {
    // According to the sub‑task constraints L == 0 and R == M-1, so we ignore them.
    if (S == D) return true;

    // ------- max humidity on the whole column interval [min(S,D), max(S,D)] -------
    int leftIdx = min(S, D);
    int rightIdx = max(S, D);
    int maxH = -1;
    for (int i = leftIdx; i <= rightIdx; ++i) {
        if (H_global[i] > maxH) maxH = H_global[i];
    }

    // ------- start interval on row 0 (containing S) -------
    int Ls = S;
    while (Ls > 0 && H_global[Ls - 1] < T_global[0]) --Ls;
    int Rs = S;
    while (Rs + 1 < M && H_global[Rs + 1] < T_global[0]) ++Rs;
    auto startInfo = seg.rangeMin(Ls, Rs);
    int startPos = startInfo.second;
    int depthStart = computeDepth(startPos);

    // ------- target interval on row 0 (containing D) -------
    int Ld = D;
    while (Ld > 0 && H_global[Ld - 1] < T_global[0]) --Ld;
    int Rd = D;
    while (Rd + 1 < M && H_global[Rd + 1] < T_global[0]) ++Rd;
    auto targetInfo = seg.rangeMin(Ld, Rd);
    int targetPos = targetInfo.second;
    int depthTarget = computeDepth(targetPos);

    int reachableDepth = min(depthStart, depthTarget);
    int maxReachableTemp = prefMaxT[reachableDepth];

    return maxReachableTemp > maxH;
}
#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...