Submission #1282216

#TimeUsernameProblemLanguageResultExecution timeMemory
1282216khanhphucscratchRainforest Jumps (APIO21_jumps)C++20
44 / 100
556 ms93156 KiB
#include "jumps.h" #include<bits/stdc++.h> using namespace std; int n, h[200005], le[200005], ri[200005], jump_max[200005][20], jumpri[200005][20], max_reach_right[200005][20]; vector<int> st[800020]; int st_max[800005]; inline bool cmp(const int x, const int y) { return h[x] < h[y]; } void build(int node, int l, int r) { if(l == r){st[node].push_back(l); st_max[node] = l;} else{ build(node*2, l, (l+r)/2); build(node*2+1, (l+r)/2+1, r); int j = 0; for(int i = 0; i < st[node*2].size(); i++){ while(j < st[node*2+1].size() && h[st[node*2+1][j]] < h[st[node*2][i]]){ st[node].push_back(st[node*2+1][j]); j++; } st[node].push_back(st[node*2][i]); } while(j < st[node*2+1].size()){ st[node].push_back(st[node*2+1][j]); j++; } if(h[st_max[node*2]] < h[st_max[node*2+1]]) st_max[node] = st_max[node*2+1]; else st_max[node] = st_max[node*2]; } } int query(int node, int l, int r, int tl, int tr, int val) { if(l > tr || r < tl) return -1; if(l >= tl && r <= tr){ int p = lower_bound(st[node].begin(), st[node].end(), val, cmp) - st[node].begin(); if(p == 0) return -1; else return st[node][p-1]; } else{ int x = query(node*2, l, (l+r)/2, tl, tr, val); int y = query(node*2+1, (l+r)/2+1, r, tl, tr, val); if(x == -1) return y; if(y == -1) return x; if(h[x] < h[y]) return y; else return x; } } int query_atleast_right(int node, int l, int r, int tl, int tr, int val) { if(l > tr || r < tl || h[st_max[node]] < h[val]) return -1; if(l == r) return st_max[node]; int y = query_atleast_right(node*2+1, (l+r)/2+1, r, tl, tr, val); if(y == -1) return query_atleast_right(node*2, l, (l+r)/2, tl, tr, val); else return y; } int query_max(int node, int l, int r, int tl, int tr) { if(l > tr || r < tl) return -1; if(l >= tl && r <= tr) return st_max[node]; else{ int x = query_max(node*2, l, (l+r)/2, tl, tr); int y = query_max(node*2+1, (l+r)/2+1, r, tl, tr); if(x == -1) return y; if(y == -1) return x; if(h[x] < h[y]) return y; else return x; } } void init(int N, vector<int> H) { n = N; for(int i = 0; i < n; i++) h[i+1] = H[i]; h[0] = h[n+1] = 1e9; ri[n+1] = n+1; for(int i = 1; i <= n; i++){ le[i] = i-1; while(h[le[i]] < h[i]) le[i] = le[le[i]]; } for(int i = n; i >= 1; i--){ ri[i] = i+1; while(h[ri[i]] < h[i]) ri[i] = ri[ri[i]]; } for(int i = 1; i <= n; i++){ if(h[le[i]] > h[ri[i]]) jump_max[i][0] = le[i]; else jump_max[i][0] = ri[i]; jumpri[i][0] = ri[i]; max_reach_right[i][0] = ri[i]; } jumpri[n+1][0] = jump_max[n+1][0] = n+1; for(int j = 1; j <= 19; j++){ for(int i = 0; i <= n+1; i++){ jump_max[i][j] = jump_max[jump_max[i][j-1]][j-1]; jumpri[i][j] = jumpri[jumpri[i][j-1]][j-1]; max_reach_right[i][j] = max(max_reach_right[i][j-1], max_reach_right[jump_max[i][j-1]][j-1]); } } build(1, 1, n); } int minimum_jumps(int l1, int r1, int l2, int r2) { l1++; r1++; l2++; r2++; //First check if it's possible int p2 = query_max(1, 1, n, l2, r2), p1 = query_atleast_right(1, 1, n, l1, r1, p2); l1 = query(1, 1, n, max(p1+1, l1), r1, p2); //We greedily choose the largest node if(l1 == -1) return -1; int u = l1; for(int i = 19; i >= 0; i--) if(jumpri[u][i] <= p2) u = jumpri[u][i]; if(u < l2) return -1; //Now find the best answer int ans = 0; u = l1; for(int i = 19; i >= 0; i--) if(h[jump_max[u][i]] < h[p2] && max_reach_right[u][i] < l2){ u = jump_max[u][i]; ans += (1 << i); } for(int i = 19; i >= 0; i--) if(jumpri[u][i] <= p2){ u = jumpri[u][i]; ans += (1 << i); } return ans; }
#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...