Submission #1324757

#TimeUsernameProblemLanguageResultExecution timeMemory
1324757pfangRainforest Jumps (APIO21_jumps)C++20
4 / 100
555 ms125648 KiB
#include <bits/stdc++.h>

using namespace std;

// find nearest left, nearest right with monotonic stack (like in prev mock)
// need bin lift table up? need log 
// We need to do this: go up left or right

int n;
vector<int> height;
vector<vector<int>> binliftL;
vector<vector<int>> binliftR;
vector<vector<int>> normalLift;

const int LOG = 26;

void init(int n1, vector<int> arr){ // find dominance by using monotonic stack
    height = arr;
    height.insert(height.begin(), INT_MAX);
    height.push_back(INT_MAX);
    n = height.size();
    vector<vector<int>> inputL(LOG, vector<int>(n));
    vector<vector<int>> inputR(LOG, vector<int>(n));
    vector<vector<int>> lifter(LOG, vector<int>(n));
    stack<int> stck; // start off from 0, so that means the left elements are being comaped to
    for(int i = 0; i < n; i++){
        while(!stck.empty() && height[stck.top()] <= height[i]){
            stck.pop(); // element is less than current ele, can be discarded now
        }
        if(stck.empty()){
            inputL[0][i] = i; // leftmost higher IS itself
        }else{
            inputL[0][i] = stck.top();
        }
        stck.push(i);
    }
    
    stack<int> stck2;
    for(int i = n-1; i >= 0; i--){
        while(!stck2.empty() && height[stck2.top()] <= height[i]){
            stck2.pop(); // element is less than current ele, can be discarded now
        }
        if(stck2.empty()){
            inputR[0][i] = i; // rightmost higher IS itself
        }else{
            inputR[0][i] = stck2.top();
        }
        stck2.push(i);
    }
    
    for(int i = 0; i < n; i++){
        // just check left and right heights
        if(height[ inputL[0][i] ] > height[ inputR[0][i] ]){
            lifter[0][i] = inputL[0][i];
        }else{
            lifter[0][i] = inputR[0][i];
        }
        
    }
    
    // bin lift (easy)
    for(int k = 1; k < LOG; k++){
        for(int i = 0; i < n; i++){
            inputL[k][i] = inputL[k-1][ inputL[k-1][i] ];
            inputR[k][i] = inputR[k-1][ inputR[k-1][i] ];
            lifter[k][i] = lifter[k-1][ lifter[k-1][i] ];
        }
    }
    binliftR = inputR;
    binliftL = inputL;
    normalLift = lifter;
}

int findIndex(int a, int b){
    for(int k = LOG - 1; k >= 0; k--){
        if(binliftR[k][a] <= b){
            a = binliftR[k][a]; // keep goiung up till either it is invalid
        }
    }
    return a;
}

int minimum_jumps(int a, int b, int c, int d){
    // method: first cases: 
    // 1: INFINITY 5 8 2 9 4 7 INFINITY or else -1s from 1-2 to 6-7. we can jump left potentially: for example, ----- 10 --4-- 7 --9- 11 4->10->11 faster than 4->7->9->11(assuming 11 is the only target)
    // how ????
    // first steo, we need to check if there is someone who blocks us in the middle (7. 9 here are examples)
    // find max in interval B+1 to c-1
    // ok, first off greedy:
    // if we have some node x that is left of B, it will either get to B (useless) or it will be stuck by something, so we rather
    // start with B and simulate jumps left to a node hgiher than middle highest (this is the hurdle we want to clear)
    //do not add these jumps. this helps us find the node in the interval which can jump rightwards (cant use max since that would go)
    // too far over
    // then, simulate a direct rightward jump(s)
    // we can continue climbing left or right depending on which one is higher
    // bruh we need to compute this
    // once we are finished climbing high edge, we check if we ge to the hurlde. (we literally have to have at the very least of this )
    // hieght when we want to go rightwards, if we can even get to the middle hurdle
    // do 1 right jump
    // or do 1 left jump if we are not at the hurlde (we have to try one more time?)
    // then check if it clears hurdle and bin lift gives us somewhere <= D
    // all other cases: keep goiung right until we can get to c, or if we cant, -1 return
    a++;
    b++;
    c++;
    d++; // account for infinities we added
    int hurdlePos;
    if(b == c-1){
        // just take a right, no need to find hurdle
        if(binliftR[0][b] <= d){
            return 1;
        }
        return -1;
    }
    // now we find hurdle
    hurdlePos = findIndex(b+1, c-1);
    // check if the max IS a hurdle? current B larger than hurdle then we good, just take a right 
    if(height[b] > height[hurdlePos]){
        if(binliftR[0][b] <= d){
            return 1;
        }
        return -1;
    }
    
    int curPos = b; // simulate jumps LEFT FIRST 
    for(int k = LOG - 1; k >= 0; k--){
        // check: IF the next left thing is less than a, we cannot take. we continue jumping until we find highest AND LESS THAN HURDLE
        if(binliftL[k][curPos] > 0 && height[binliftL[k][curPos]] < height[hurdlePos]){
            curPos = binliftL[k][curPos];
        }
    }
    
        int ans = 0;
    // case 1: firect right jump. first take a left jumpr egardless of hurdle. (guarenteed higher tha hurdle for this left hump, since it would)
    // already take it in the loop abive, so all we need to check is <= D
    if(binliftL[0][curPos] >= a){
        if(binliftR[0][ binliftL[0][curPos] ] <= d){
            return 1;
        }
    }else{
        for(int k = LOG - 1; k >= 0; k--){
            if(height[ normalLift[k][curPos] ] <= height[hurdlePos]){
                curPos = normalLift[k][curPos];
                ans += 1 << k;
            }
        }
        
        if(curPos == hurdlePos){
            if(binliftR[0][curPos] <= d){
                return ans + 1;
            }
            return -1;
        }
        
        // do the left then right again 
        if(binliftL[0][curPos] >= a && binliftR[0][ binliftL[0][curPos] ] <= d){
            return ans + 2; // both jumps count towards our cost
        }
    }
    // last case: right ward . keep going right until we cant, check if it is within c, D 
    for(int k = LOG - 1; k >= 0; k--){
        if(binliftR[k][curPos] < c){ // when we get to rightmost from c, we have to stop and take the smallest step possible (which is most optimal; if it is -1, then we already cant get there)
            curPos = binliftR[k][curPos];
            ans += 1 << k;
        }
    }
    int LASTPOS = binliftR[0][curPos]; // we use smallest jump ppossible: k = 0
    if(LASTPOS >= c && LASTPOS <= 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...