Submission #813445

# Submission time Handle Problem Language Result Execution time Memory
813445 2023-08-07T18:00:57 Z kostka Fountain (eJOI20_fountain) C++14
100 / 100
157 ms 16480 KB
#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
1 Correct 0 ms 212 KB Output is correct
2 Correct 1 ms 340 KB Output is correct
3 Correct 1 ms 340 KB Output is correct
4 Correct 1 ms 468 KB Output is correct
5 Correct 1 ms 456 KB Output is correct
6 Correct 1 ms 468 KB Output is correct
7 Correct 1 ms 464 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 79 ms 14952 KB Output is correct
2 Correct 112 ms 13904 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 0 ms 212 KB Output is correct
2 Correct 1 ms 340 KB Output is correct
3 Correct 1 ms 340 KB Output is correct
4 Correct 1 ms 468 KB Output is correct
5 Correct 1 ms 456 KB Output is correct
6 Correct 1 ms 468 KB Output is correct
7 Correct 1 ms 464 KB Output is correct
8 Correct 79 ms 14952 KB Output is correct
9 Correct 112 ms 13904 KB Output is correct
10 Correct 1 ms 452 KB Output is correct
11 Correct 47 ms 9040 KB Output is correct
12 Correct 157 ms 16164 KB Output is correct
13 Correct 125 ms 16184 KB Output is correct
14 Correct 96 ms 16124 KB Output is correct
15 Correct 82 ms 16480 KB Output is correct