제출 #1345684

#제출 시각아이디문제언어결과실행 시간메모리
1345684tsengang밀림 점프 (APIO21_jumps)C++20
27 / 100
289 ms49756 KiB
#include <vector>
#include <algorithm>
#include <stack>

using namespace std;

const int MAXN = 200005;
const int LOGN = 19;

int N_size;
int H_val[MAXN];
int L[MAXN], R[MAXN];
int st_high[MAXN][LOGN];
int st_right[MAXN][LOGN];
int st_max[MAXN][LOGN]; // Sparse table for RMQ on heights

// Build Sparse Table for RMQ
void build_sparse_table(int n) {
    for (int i = 0; i < n; i++) st_max[i][0] = i;
    for (int j = 1; j < LOGN; j++) {
        for (int i = 0; i + (1 << j) <= n; i++) {
            int a = st_max[i][j - 1];
            int b = st_max[i + (1 << (j - 1))][j - 1];
            st_max[i][j] = (H_val[a] > H_val[b]) ? a : b;
        }
    }
}

int query_max_idx(int l, int r) {
    int len = r - l + 1;
    int j = 31 - __builtin_clz(len);
    int a = st_max[l][j];
    int b = st_max[r - (1 << j) + 1][j];
    return (H_val[a] > H_val[b]) ? a : b;
}

void init(int N, vector<int> H) {
    N_size = N;
    for (int i = 0; i < N; i++) H_val[i] = H[i];
    build_sparse_table(N);

    // Find Nearest Greater Elements using Monotonic Stack
    stack<int> s;
    for (int i = 0; i < N; i++) {
        while (!s.empty() && H[s.top()] < H[i]) s.pop();
        L[i] = s.empty() ? -1 : s.top();
        s.push(i);
    }
    while (!s.empty()) s.pop();
    for (int i = N - 1; i >= 0; i--) {
        while (!s.empty() && H[s.top()] < H[i]) s.pop();
        R[i] = s.empty() ? -1 : s.top();
        s.push(i);
    }

    // Binary Lifting Preprocessing
    for (int i = 0; i < N; i++) {
        // High jump: move to the taller of the two neighbors
        if (L[i] != -1 && R[i] != -1) {
            st_high[i][0] = (H[L[i]] > H[R[i]]) ? L[i] : R[i];
        } else if (L[i] != -1) {
            st_high[i][0] = L[i];
        } else {
            st_high[i][0] = R[i];
        }
        
        // Right jump: specifically for closing the gap to [C, D]
        st_right[i][0] = R[i];
    }

    for (int j = 1; j < LOGN; j++) {
        for (int i = 0; i < N; i++) {
            if (st_high[i][j - 1] != -1)
                st_high[i][j] = st_high[st_high[i][j - 1]][j - 1];
            else st_high[i][j] = -1;

            if (st_right[i][j - 1] != -1)
                st_right[i][j] = st_right[st_right[i][j - 1]][j - 1];
            else st_right[i][j] = -1;
        }
    }
}

int minimum_jumps(int A, int B, int C, int D) {
    int max_mid = (B + 1 <= C - 1) ? H_val[query_max_idx(B + 1, C - 1)] : -1;
    int max_target = H_val[query_max_idx(C, D)];

    // 1. Find optimal starting point in [A, B]
    // We want the tallest tree that is shorter than max_target.
    int curr = query_max_idx(A, B);
    for (int j = LOGN - 1; j >= 0; j--) {
        // If the current tree is too tall, try to find a shorter one in the range
        // that is still closer to the target height. 
        // A simpler way: binary search the range [A, B] for the rightmost tree 
        // that is shorter than max_target.
    }
    
    // Refined starting point: highest tree in [A, B] that can't "jump over" the target range
    // specifically we start from the rightmost tree in [A, B] that is shorter than the tallest tree in [C, D]
    int s = B;
    for (int j = LOGN - 1; j >= 0; j--) {
        int temp = st_max[s][0]; // current
        // Optimization: use the sparse table to find the best start
    }
    // Simple start check:
    int start = B;
    for(int j = LOGN-1; j >= 0; j--) {
        int step = (1 << j);
        if(start - step + 1 >= A && H_val[query_max_idx(start - step + 1, B)] < max_target) {
            // Keep searching for the tallest valid tree in the range
        }
    }
    
    // Re-assign start to the tallest tree in [A, B] that is < max_target
    int best_s = query_max_idx(A, B);
    // If the tallest in [A, B] is already taller than max_target, 
    // we must find a shorter one within [A, B].
    if (H_val[best_s] > max_target) return -1; 
    
    int cur = best_s;
    int ans = 0;

    // 2. High Jump Phase: Jump as high as possible without overshooting
    for (int j = LOGN - 1; j >= 0; j--) {
        int nxt = st_high[cur][j];
        if (nxt != -1 && H_val[nxt] < H_val[query_max_idx(C, D)] && (R[nxt] == -1 || R[nxt] <= D)) {
            // Additional check: only high jump if it doesn't bypass C entirely
            if (nxt < C) {
                cur = nxt;
                ans += (1 << j);
            }
        }
    }

    // 3. Right Jump Phase: Move right into the range [C, D]
    for (int j = LOGN - 1; j >= 0; j--) {
        int nxt = st_right[cur][j];
        if (nxt != -1 && H_val[nxt] <= max_target && nxt < C) {
            cur = nxt;
            ans += (1 << j);
        }
    }

    if (R[cur] != -1 && R[cur] >= C && R[cur] <= D) return ans + 1;
    return -1;
}
#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...