Hi Everyone,
I am doing the USACO Gold problem Snow Boots. I am experiencing inconsistency in my code between the USACO judge and the IntelliJ IDEA CE runTime environment.
My solution is very similar to the solution for Bit Inversions. Using binary search, I created a matrix depthIndices
that stores all indices for each snow depth in sortedDepths
. For each possible depth, I used the Bit Inversions algorithm to find the width of the maximum “gap”, a contiguous sequence of tiles whose snow depth exceeds the possible depth. One more than this is the minimum step size for that depth. The results are stored in minStep
.
Then, for each boot, I used binary search to find the greatest recorded depth less than or equal to its depth, and determined whether FJ can make the trek. My code is below:
import java.io.*;
import java.util.*;
public class SnowBoots {
public static void main(String[] args) throws IOException {
// BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
// PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(System.out)));
BufferedReader in = new BufferedReader(new FileReader("snowboots.in"));
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("snowboots.out")));
StringTokenizer st = new StringTokenizer(in.readLine());
int numTiles = Integer.parseInt(st.nextToken());
int numBoots = Integer.parseInt(st.nextToken());
int[] tileDepths = new int[numTiles];
HashSet<Integer> distinctDepths = new HashSet<>();
StringTokenizer stt = new StringTokenizer(in.readLine());
for (int i = 0; i < numTiles; i++) {
tileDepths[i] = Integer.parseInt(stt.nextToken());
distinctDepths.add(tileDepths[i]);
}
Integer[] sortedDepths = distinctDepths.stream().sorted().toArray(Integer[]::new);
// Given a depth, all indexes in tiles with that depth
ArrayList<ArrayList<Integer>> depthIndices = new ArrayList<>(sortedDepths.length);
for (int i = 0; i < sortedDepths.length; i++) {
depthIndices.add(new ArrayList<>());
}
for (int i = 0; i < numTiles; i++) {
int index = Arrays.binarySearch(sortedDepths, tileDepths[i]);
depthIndices.get(index).add(i);
}
// Given an index of sortedDepths, minimum step needed to pass
int[] minStep = new int[sortedDepths.length];
minStep[minStep.length - 1] = 1;
// TreeSet containing start and ends of gaps
// As standard end is one more than actual end
TreeSet<GapPoint> gaps = new TreeSet<>();
// Max Heap containing lengths of gaps
PriorityQueue<Integer> gapLengths = new PriorityQueue<>(Collections.reverseOrder());
// Array containing frequency of gaps
int[] gapFrequencies = new int[numTiles];
for (int i = minStep.length - 2; i >= 0; i--) {
int start = depthIndices.get(i + 1).get(0);
for (int index = 1; index < depthIndices.get(i + 1).size(); index++) {
if (depthIndices.get(i + 1).get(index) - depthIndices.get(i + 1).get(index - 1) > 1) {
add(gaps, gapLengths, gapFrequencies, start, index);
start = index;
}
}
add(gaps, gapLengths, gapFrequencies, start, depthIndices.get(i + 1).get(depthIndices.get(i + 1).size() - 1) + 1);
while (gapFrequencies[gapLengths.peek() - 1] == 0) gapLengths.poll();
minStep[i] = gapLengths.peek() + 1;
}
// For each boot, binary search to find largest depth smaller than it
for (int b = 0; b < numBoots; b++) {
StringTokenizer stb = new StringTokenizer(in.readLine());
int maxDepth = Integer.parseInt(stb.nextToken());
int maxStep = Integer.parseInt(stb.nextToken());
int index = Arrays.binarySearch(sortedDepths, maxDepth);
if (index < 0) index = -index - 2;
out.println(maxStep >= minStep[index] ? "1" : "0");
}
out.close();
}
static void add(TreeSet<GapPoint> gaps, PriorityQueue<Integer> gapLengths, int[] gapFrequencies, int start, int end) {
GapPoint floor = gaps.floor(new GapPoint(start, true));
GapPoint ceiling = gaps.ceiling(new GapPoint(end, false));
// Determine left side of gap
if (floor != null) {
assert !floor.start;
if (floor.index == start) {
gaps.remove(floor);
GapPoint begin = gaps.lower(floor);
gapFrequencies[floor.index - begin.index - 1]--;
start = begin.index;
}
}
// Determine right side of gap
if (ceiling != null) {
assert ceiling.start;
if (ceiling.index == end) {
gaps.remove(ceiling);
GapPoint ending = gaps.higher(ceiling);
gapFrequencies[ending.index - ceiling.index - 1]--;
end = ending.index;
}
}
gaps.add(new GapPoint(start, true));
gaps.add(new GapPoint(end, false));
gapLengths.add(end - start);
gapFrequencies[end - start - 1]++;
}
}
class GapPoint implements Comparable<GapPoint> {
public int index;
public boolean start;
public GapPoint(int index, boolean start) {
this.index = index;
this.start = start;
}
public int compareTo(GapPoint gp) {
return this.index - gp.index;
}
}
When run on USACO judges, the first four test cases get AC, but test cases 5-12 get an exclamation mark. I checked my code and it only stores at most 13 * 10^5 ints, which is below the memory limit. This means that there must be a runtime error.
When I ran the code on IntelliJ IDEA CE using the Command Line app, it does not have any runtime errors. I was wondering why this inconsistency is happening. Below are the two screenshots of the runs.
Thanks,
rayfish