제출 #654724

#제출 시각아이디문제언어결과실행 시간메모리
654724Sam_a17밀림 점프 (APIO21_jumps)C++14
100 / 100
2690 ms64220 KiB
#include <bits/stdc++.h> using namespace std; #define dbg(x) cerr << #x << " " << x << endl; #define ll long long const int maxN = 2e5 + 10, LOG = 22, inf = 1e8; int h[maxN], n, pre[maxN][LOG], nxt[maxN][LOG]; int mx[maxN][LOG]; struct segTree { vector<pair<long long, int>> mTree; int size; void init(long long n) { size = 1; while(size < n) { size *= 2; } mTree.assign(2 * size - 1, {0, 0}); } pair<ll, ll> combine(pair<ll, ll> a, pair<ll, ll> b) { if(a.first > b.first) { return a; } else { return b; } } void upd(int u, long long v, int x, int lx, int rx) { // set value at pos u if(rx - lx == 1) { mTree[x] = {v, lx}; return; } int m = (lx + rx) / 2; if(u < m) { upd(u, v, 2 * x + 1, lx, m); }else { upd(u, v, 2 * x + 2, m, rx); } mTree[x] = combine(mTree[2 * x + 1], mTree[2 * x + 2]); } void upd(int u, long long v) { upd(u, v, 0, 0, size); } pair<ll, ll> qry (int l, int r, int x, int lx, int rx) { // range queries if(l >= rx || lx >= r) { return {INT64_MIN, -1}; } if(lx >= l && r >= rx) { return mTree[x]; } int m = (rx + lx) / 2; auto s1 = qry(l, r, 2 * x + 1, lx, m); auto s2 = qry(l, r, 2 * x + 2, m, rx); return combine(s1, s2); } pair<ll, ll> qry(int l, int r) { return qry(l, r, 0, 0, size); } }; segTree seg; void init(int N, std::vector<int> H) { n = N, seg.init(n + 1); for(int i = 0; i < N; i++) { h[i] = H[i]; seg.upd(i, h[i]); // nxt[i][0] = pre[i][0] = i; } stack<pair<int, int>> st; for(int i = 0; i < N; i++) { while(!st.empty() && h[i] > st.top().first) { nxt[st.top().second][0] = i; st.pop(); } st.push({h[i], i}); } while(!st.empty()) st.pop(); for(int i = N - 1; i >= 0; i--) { while(!st.empty() && h[i] > st.top().first) { pre[st.top().second][0] = i; st.pop(); } st.push({h[i], i}); } for(int i = 0; i < N; i++) { if(h[nxt[i][0]] >= h[pre[i][0]]) { mx[i][0] = nxt[i][0]; } else { mx[i][0] = pre[i][0]; } } for(int j = 1; j < LOG; j++) { for(int i = 0; i < N; i++) { mx[i][j] = mx[mx[i][j - 1]][j - 1]; nxt[i][j] = nxt[nxt[i][j - 1]][j - 1]; pre[i][j] = pre[pre[i][j - 1]][j - 1]; } } } int get_mx(int mid, int node) { for(int i = 0; i < LOG; i++) { if(mid & (1 << i)) { node = mx[node][i]; } } return node; } int get_r(int mid, int node) { for(int i = 0; i < LOG; i++) { if(mid & (1 << i)) { node = nxt[node][i]; } } return node; } int minimum_jumps(int A, int B, int C, int D) { auto maxim = seg.qry(B, C); auto maxim_ = seg.qry(C, D + 1); if(maxim.first >= maxim_.first) { return -1; } int l = A, r = B, st = -1; while(l <= r) { int mid = (l + r) / 2; if(seg.qry(mid, r + 1).first < maxim_.first) { st = mid; r = mid - 1; } else { l = mid + 1; } } if(st == -1) { return -1; } A = seg.qry(st, B + 1).second; int ina = 0, inb = maxN, answ = 0; while(ina <= inb) { int mid = (ina + inb) / 2; int pos = get_mx(mid, A); if(h[pos] >= maxim.first) { answ = mid; inb = mid - 1; } else { ina = mid + 1; } } int pos = get_mx(answ, A); if(pos >= C && pos <= D) return answ; if(h[pos] >= maxim_.first) { answ--; } pos = get_mx(answ, A); ina = 0, inb = maxN; int answ2 = 0; while(ina <= inb) { int mid = (ina + inb) / 2; int pos2 = get_r(mid, pos); if(pos2 >= C) { answ2 = mid; inb = mid - 1; } else { ina = mid + 1; } } pos = get_r(answ2, pos); return answ2 + answ; }
#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...