Editorial for WC '15 Contest 4 S1 - Shootout
Submitting an official solution before solving the problem yourself is a bannable offence.
We are given  henchmen and 
 doors located at distinct positions on the number line. Henchman 
 is in Bond's line of sight if and only if every door 
 with 
 value less than 
 is opened. That is, for the 
-th line of output, we should count the number of henchmen such that no 
 value from 
 to 
 is greater than 
. To illustrate the intended computations, a naïve solution is given here which runs in 
.
#include <iostream>
using namespace std;
int N, M, H[200005], D[200005];
int main() {
  cin >> N >> M;
  for (int i = 0; i < N; i++) cin >> H[i];
  for (int i = 0; i < M; i++) cin >> D[i];
  for (int i = 0; i < M; i++) {
    int ans = 0;
    for (int j = 0; j < N; j++) {
      bool blocked = false;
      for (int k = i + 1; k < M; k++)
        if (D[i] < H[j]) blocked = true;
      if (!blocked) ans++;
    }
    cout << ans << endl;
  }
  return 0;
}
This solution is only meant to be given only 3/17 of the points (through the first subtask, where , so 
 is no larger than 
). The second subtask was designed for various 
 solutions which we will not discuss here.
For up to the third subtask, we can go for an  solution which eliminates the innermost for-loop of 
k. How? Observe that the inner loop is asking the question "does there exist a value in  which is less than the current 
?" This is actually equivalent to asking if the minimum value in 
 is less than 
. Let the array 
 be such that 
 stores the minimum 
 value from 
 to 
. To compute this array, just loop backwards from 
 to 
 and store the minimum of the minimum so far with the current 
 value. This simple solution is given 11/17 of the points.
It is also possible to get 11/17 points with a more complex solution, which involves sorting, searching, and erasing from an array.
For a full solution, let's start by sorting the  henchmen in increasing order of position, which can be done using any 
 time sorting algorithm. Let's similarly sort the 
 doors in 
 time – however in this case, we'll need to keep each door's original index associated with its position after the sort (as opposed to only sorting the 
 door positions independently, where info about the original position is lost). To accomplish this, we can represent each door as a pair of integers 
, and compare these pairs by only their position value in the sorting algorithm. To use this with the built-in sorting function of certain languages, we may need to define a custom class and/or comparator, or use something like C++'s 
std::pair.
Now, as we simulate opening all of the doors in order, we'd like to maintain one running index for each of the two sorted lists. Firstly, we need to keep track of the index  of the current first henchmen not in Bond's line of fire (or 
 if there's no such henchman). Secondly, we need the index 
 of the current first closed door (or 
 if there's no such door). We can observe that exactly the first 
 sorted henchmen will be in Bond's line of fire, such that the 
-th henchmen is the first one further from Bond than the 
-th door in the sorted list.
When door  is opened, we can update 
 by repeatedly incrementing it as long as it's no larger than 
, and the original index of the 
-th door in the sorted list is smaller than or equal to 
 (note that 
 never decreases). When a given door is opened, 
 might stay the same or be incremented many times, but over the course of the entire simulation, it will only be incremented 
 times, so these updates will take 
 time in total.
After the index  has been updated for door 
, we can use it to update 
 accordingly (which will give us the 
-th answer). Similarly to the above approach, we can repeatedly increment 
 as long as it's no larger than 
, and the index of the 
-th henchman in the sorted list is before the index of the 
-th door in the sorted list. Likewise, 
 will be incremented a total of 
 times throughout the entire simulation, which can be handled in 
 time.
The sorting of the two arrays dominate over the simulation, so the overall running time is .
Alternatively, we don't have to keep track of the  value. In this case, the second while-loop may be replaced with a binary search on the sorted array of henchmen, querying for the first henchman position which is not less than the position of the current door. This position is the answer, since all henchmen before will also be in the line of sight.
Alternatively, we can put all henchmen and doors into the same array of pairs and sort them by position (but still remembering the index of each door). When we open a door, we erase the door  from the sorted array and loop 
 upwards until we skip over all of the erased doors while counting the number of henchmen encountered in the same loop. The sorting also dominates in this variation, but as we are sorting a list of size 
, the solution will run in 
 time.
Comments