제출 #795812

#제출 시각아이디문제언어결과실행 시간메모리
795812GusterGoose27밀림 점프 (APIO21_jumps)C++17
100 / 100
1187 ms40360 KiB
#include "jumps.h"

#include <bits/stdc++.h>

using namespace std;

const int MAXN = 2e5+5;
const int MAXB = 20;
typedef pair<int, int> pii;
int height[MAXN];
int great[MAXN][2];
int nxt[MAXN][MAXB];
int depth[MAXN];
int n;

int get_max(int i, int j) { // returns rightmost in case
    if (i == -1) return j;
    if (j == -1) return i;
    return height[i] > height[j] ? i : j;
}

class stree {
public:
    int lp, rp;
    stree *l = nullptr;
    stree *r = nullptr;
    int mx = 0;
    stree(int lv, int rv) {
        lp = lv;
        rp = rv;
        if (lp < rp) {
            int m = (lp+rp)/2;
            l = new stree(lp, m);
            r = new stree(m+1, rp);
            reupd();
        }
        else mx = lp;
    }
    void reupd() {
        mx = get_max(l->mx, r->mx);
    }
    int range_mx(int lv, int rv) {
        if (lp > rv || rp < lv) return -1;
        if (lp >= lv && rp <= rv) return mx;
        return get_max(l->range_mx(lv, rv), r->range_mx(lv, rv));
    }
    int right_mx(int lv, int rv, int v) { // rightmost pos in lv...rv st height[i] > v
        if (lp > rv || rp < lv || height[mx] < v) return -1;
        if (lp == rp) return lp;
        int rq = r->right_mx(lv, rv, v);
        return rq == -1 ? l->right_mx(lv, rv, v) : rq;
    }
};

stree *tree;

void init(int N, vector<int> H) {
    n = N;
    height[n] = MAXN;
    for (int i = 0; i < n; i++) height[i] = H[i];
    tree = new stree(0, n-1);
    vector<int> rvals;
    depth[n] = 0;
    rvals.push_back(n);
    for (int i = n-1; i >= 0; i--) {
        while (height[i] > height[rvals.back()]) rvals.pop_back();
        great[i][0] = rvals.back();
        depth[i] = 1+depth[rvals.back()];
        rvals.push_back(i);
    }
    rvals.clear();
    rvals.push_back(-1);
    for (int i = 0; i < n; i++) {
        while (rvals.size() > 1 && height[i] > height[rvals.back()]) rvals.pop_back();
        great[i][1] = rvals.back();
        rvals.push_back(i);
    }
    for (int i = 0; i < n; i++) {
        nxt[i][0] = i;
        if (great[i][0] < n) nxt[i][0] = get_max(great[i][0], nxt[i][0]);
        if (great[i][1] >= 0) nxt[i][0] = get_max(great[i][1], nxt[i][0]);
    }
    for (int j = 1; j < MAXB; j++) {
        for (int i = 0; i < n; i++) {
            nxt[i][j] = nxt[nxt[i][j-1]][j-1];
        }
    }
}

int minimum_jumps(int a, int b, int c, int d) {
    int rmx = height[tree->range_mx(c, d)];
    if (height[b] > rmx) return -1;
    if (c == b+1) {
        return 1;
    }
    int dpos = tree->range_mx(b+1, c-1);
    int div = height[dpos];
    if (div > rmx) return -1;
    int lmx = tree->range_mx(a, b);
    int lgreat = tree->right_mx(0, b, div);
    int s = lmx;
    if (lgreat >= a) {
        if (height[lgreat] < rmx) return 1;
        s = tree->range_mx(lgreat+1, b);
    }
    int mv = 0;
    for (int i = MAXB-1; i >= 0; i--) {
        if (height[nxt[s][i]] <= div) {
            s = nxt[s][i];
            mv += (1<<i);
        }
    }
    // now, we either go to the left or we go to the right
    if (height[s] == div) return 1+mv;
    assert(lgreat != -1);
    if (height[lgreat] < rmx) return 2+mv;
    return mv+1+depth[s]-depth[dpos];
}
#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...