제출 #1162845

#제출 시각아이디문제언어결과실행 시간메모리
1162845brinton밀림 점프 (APIO21_jumps)C++20
48 / 100
402 ms57704 KiB
#include "jumps.h"

#include <bits/stdc++.h>
using namespace std;
#define inf 1000000
vector<vector<int>> edges;
vector<int> H;
vector<vector<int>> big,small,spt;
int N;
int k;
void init(int iN, std::vector<int> iH) {
  N = iN;
  H = iH;
  // create DAG using monotic array
  stack<int> st;
  edges.resize(N+1);
  // create front
  for(int i = 0;i < N;i++){
    while(!st.empty() && st.top() < H[i]){
      st.pop();
    }
    
    if(!st.empty()){
      edges[H[i]].push_back(st.top());
    }
    st.push(H[i]);
  }

  while(!st.empty()) st.pop();
  // from back
  for(int i = N-1;i >= 0;i--){
    while(!st.empty() && st.top() < H[i]){
      st.pop();
    }
    
    if(!st.empty()){
      edges[H[i]].push_back(st.top());
    }
    st.push(H[i]);
  }

  for(auto &i:edges){
    if(i.size() == 0){
      i.push_back(-1);
      i.push_back(-1);
      continue;
    }
    if(i.size() == 1){
      i.push_back(i[0]);
      continue;
    }
    if(i[0] < i[1]) swap(i[0],i[1]);
  }
  // edges[0] -> big, edges[1] -> small
  //create edges ok, lets create binary jump
  k = __lg(N+1);
  big = small = vector<vector<int>>(k+1,vector<int>(N+1,0));
  // zero layer
  for(int i = 1;i <= N;i++){
    big[0][i] = edges[i][0];
    small[0][i] = edges[i][1];
  }
  for(int l = 1;l <= k;l++){
    for(int i = 1;i <= N;i++){
      if(big[l-1][i] == -1){
        big[l][i] = -1;
      }else{
        big[l][i] = big[l-1][big[l-1][i]];
      }
      if(small[l-1][i] == -1){
        small[l][i] = -1;
      }else{
        small[l][i] = small[l-1][small[l-1][i]];
      }
    }
  }
  spt = vector<vector<int>>(k+1,vector<int>(N,0));// range max;
  spt[0] = H;
  for(int l = 1;l <= k;l++){
    for(int i = 0;i+(1 << (l-1)) < N;i++){
      spt[l][i] = max(spt[l-1][i],spt[l-1][i+(1 << (l-1))]);
    }
  }
  // sparse table
}
int get_max(int l,int r){
  int len = (r-l+1);
  int layer = __lg(len);
  return max(spt[layer][l],spt[layer][r-(1 << layer)+1]);
}
int minimum_jumps(int A, int B, int C, int D) {
  // A <= B and C == D
  // add find start point
  int cur = B;
  if(get_max(B,C-1) > H[C])return -1;
  int bottom = A;
  int top = B;
  while(bottom <= top){
    int mid = (bottom+top)/2;
    if(get_max(mid,C-1) < H[C]){
      // ok
      cur = min(cur,mid);
      top = mid-1;
    }else{
      bottom = mid+1;
    }
  }
  cur = get_max(cur,B);
  
  // cur is the start point
  int cnt = 0;
  for(int l = k;l >= 0;l--){
    if(big[l][cur] != -1 && big[l][cur] <= H[C]){
      cur = big[l][cur];
      cnt+=(1 << l);
    }
  }
  for(int l = k;l >= 0;l--){
    if(small[l][cur] != -1 && small[l][cur] <= H[C]){
      cur = small[l][cur];
      cnt+=(1 << l);
    }
  }
  if(cur != H[C]){
    return -1;
  }else{
    return cnt;
  }
}

// grader

// #include "jumps.h"

// #include <cassert>
// #include <cstdio>

// #include <vector>

// int main() {
//   int N, Q;
//   assert(2 == scanf("%d %d", &N, &Q));
//   std::vector<int> H(N);
//   for (int i = 0; i < N; ++i) {
//     assert(1 == scanf("%d", &H[i]));
//   }
//   init(N, H);

//   for (int i = 0; i < Q; ++i) {
//     int A, B, C, D;
//     assert(4 == scanf("%d %d %d %d", &A, &B, &C, &D));
//     printf("%d\n", minimum_jumps(A, B, C, D));
//   }
//   return 0;
// }
#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...