제출 #1162901

#제출 시각아이디문제언어결과실행 시간메모리
1162901brinton밀림 점프 (APIO21_jumps)C++20
48 / 100
441 ms57696 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
  int endPoint = get_max(C,D);
  // add find start point
  int cur = B;
  if(get_max(B,C-1) > endPoint)return -1;
  {  
    int bottom = A;
    int top = B;
    while(bottom <= top){
      int mid = (bottom+top)/2;
      if(get_max(mid,C-1) < endPoint){
        // ok
        cur = min(cur,mid);
        top = mid-1;
      }else{
        bottom = mid+1;
      }
    }
  }
  cur = get_max(cur,B);// value
  // add find endPoint point
  {
    int bottom = C;
    int top = D;
    while(bottom <= top){
      int mid = (bottom+top)/2;
      if(get_max(C,mid) > max(cur,get_max(B,C-1))){
        // ok;
        endPoint = get_max(C,mid);
        top = mid-1;
      }else{
        bottom = mid+1;
      }
    }
  }
  // cout << cur << " " << endPoint << endl;
  // cur is the start point
  int cnt = 0;
  for(int l = k;l >= 0;l--){
    if(big[l][cur] != -1 && big[l][cur] <= endPoint){
      cur = big[l][cur];
      cnt+=(1 << l);
    }
  }
  for(int l = k;l >= 0;l--){
    if(small[l][cur] != -1 && small[l][cur] <= endPoint){
      cur = small[l][cur];
      cnt+=(1 << l);
    }
  }
  if(cur != endPoint){
    // cout << "?";
    return -1;
  }else{
    return cnt;
  }
}
#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...