POI 2010 - Frog

Authors: Benjamin Qi, Justin Ji

Optional: Linear Memory Binary Lifting

While not necessary for this problem, you can use linear memory binary lifting to answer the queries online.

Explanation

To calculate the kk-th closest rock from a certain location, we maintain a sliding window of size k+1k+1. Essentially, we sweep left to right, and keep on moving the window right until either:

  1. The window cannot be moved right any further.
  2. Moving the window to the right would increase the maximum distance from this current location.

Afterwards, we can proceed to binary lift to get our answer. However, directly calculating binary lifts the traditional way would take up too much memory. From here, there are two ways to proceed:

Implementation 1

Iterate over the power of two we are lifting on in increasing order. Similar to binary exponentiation, we calculate the 2i2^{i}-th next location at every step, and check if we need to use this current lift.

Time Complexity: O(NlogM)\mathcal{O}(N\log M)

Space Complexity: O(N)\mathcal{O}(N)

C++

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int main() {
cin.tie(0)->sync_with_stdio(0);
int n, k;
ll m;
cin >> n >> k >> m;
vector<ll> rocks(n);

Implementation 2

Observe that a functional graph is constructed through these jumps. After nn jumps, any node that we start from will end up being inside a cycle. Thus, we can calculate our binary lifts like normal, and calculate the number of jumps, modulo the cycle size.

Time Complexity: O(NlogN)\mathcal{O}(N\log N)

Space Complexity: O(NlogN)\mathcal{O}(N\log N)

C++

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int main() {
cin.tie(0)->sync_with_stdio(0);
int n, k;
ll m;
cin >> n >> k >> m;
vector<ll> rocks(n);

Join the USACO Forum!

Stuck on a problem, or don't understand a module? Join the USACO Forum and get help from other competitive programmers!