이 제출은 이전 버전의 oj.uz에서 채점하였습니다. 현재는 제출 당시와는 다른 서버에서 채점을 하기 때문에, 다시 제출하면 결과가 달라질 수도 있습니다.
#include "bits/stdc++.h"
using namespace std;
struct reservoir
{
  int D, C;
  int next_larger_reservoir = 0;
};
const int LOGN = 17;
int N, Q;
vector<reservoir> reservoirs;
// This function generate edges from each reservoir to the
// next reservoir that is strictly larger in diamater
// below us.
void CalculateEdges()
{
  stack<int> S;
  for (int i = 1; i <= N; i++)
  {
    // If there is an reservoir on the stack that is smaller than us
    // then pop it from the stack and set it edge to the reservoir
    // that we are currently considering.
    while (!S.empty() and reservoirs[S.top()].D < reservoirs[i].D)
    {
      int s = S.top();
      S.pop();
      reservoirs[s].next_larger_reservoir = i;
    }
    // At the end, just push the current reservoir on the stack.
    S.push(i);
  }
}
// The skip pointers will keep two values, the destination and total capacity
// of all of the reservoirs that can be reached using 2^i steps for each i.
struct SkipPointer
{
  int destination = 0, total_capacity;
};
vector<vector<SkipPointer>> skip_pointers;
void CalculateSkipPointers()
{
  skip_pointers.resize(LOGN);
  skip_pointers[0].resize(N+1);
  // Here we are setting the first level of skip pointers.
  // We use the edges we calculated in the previous step to set the 
  // next destination (reachable by using 2^0 steps),
  // and total capacity is just the capacity of this reservoir.
  for (int i = 0; i < N; i++)
  {
    skip_pointers[0][i].destination = reservoirs[i].next_larger_reservoir;
    skip_pointers[0][i].total_capacity = reservoirs[i].C;
  }
  // Now for each level, we calculate the corresponding skip pointers.
  for (int log = 1; log < LOGN; log++)
  {
    skip_pointers[log].resize(reservoirs.size());
    for (int i = 1; i <= N; i++)
    {
      // Here we take the destination from the (log-1) level,
      // i.e. that is reachable by using 2^(log-1) steps.
      int previous_destination = skip_pointers[log - 1][i].destination;
      // If it is equal to 0, that means that we cannot go any further,
      // so we just keep the destination (will be equal to -1 by default),
      // and we just assign the previous total capacit to this skip pointer.
      if (previous_destination == 0)
      {
        skip_pointers[log][i].total_capacity = skip_pointers[log - 1][i].total_capacity;
      }
      // Otherwise, we update the destination, by going next 2^(log-1) steps,
      // (so we use 2^(log-1) + 2^(log-1) = 2^log steps in total),
      // and the total_capacity of all the reservoirs on the way to the 
      // destination is equal to the sum of these two skip pointers that we used
      // to get here.
      else
      {
        skip_pointers[log][i].destination = \
          skip_pointers[log - 1][previous_destination].destination;
        skip_pointers[log][i].total_capacity = \
          skip_pointers[log - 1][i].total_capacity + \
          skip_pointers[log - 1][previous_destination].total_capacity;
      }
    }
  }
}
void HandleQueries()
{
  for (int i = 0; i < Q; i++)
  {
    int R, V;
    cin >> R >> V;
    for (int log = LOGN - 1; log >= 0; log--)
    {
      if (R != 0 and skip_pointers[log][R].total_capacity < V)
      {
        V -= skip_pointers[log][R].total_capacity;
        R = skip_pointers[log][R].destination;
      }
    }
    cout << R << "\n";
  }
}
int main()
{
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
  cin >> N >> Q;
  reservoirs.resize(N+1);
  for (int i = 1; i <= N; i++)
  {
    cin >> reservoirs[i].D >> reservoirs[i].C;
  }
  CalculateEdges();
  CalculateSkipPointers();
  HandleQueries();
}
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... | 
| # | Verdict  | Execution time | Memory | Grader output | 
|---|
| Fetching results... |