ANSWER
Essentially, if you know how many numbers will be positive and how many will be negative, you can just multiply both of these counts by the accumulated query total (and *-1 for negatives).
Work out the total count for how many -/+ there are and the total sum for all these values at each step. E.g. add +1 to all until all negatives are positive, and add -1 to all until all positives are negative, store the results of each step (the -/+ counts and total sum of all -/+ values).
You can now reference the total sum and the total -/+ counts for each step to work out the result of each query.
You will also need to change the return type of both the playingWithNumbers method and the result array, from int to long!
static long[] playingWithNumbers(int[] arr, int[] queries) {
long[] results = new long[queries.length];
List<Integer> negatives = new ArrayList<>(arr.length);
List<Integer> positives = new ArrayList<>(arr.length);
long negativeSum = 0;
long positiveSum = 0;
for (int i : arr) {
if (i < 0) {
negatives.add(i);
negativeSum += i;
} else {
positives.add(i);
positiveSum += i;
}
}
int negativeCount = negatives.size();
int positiveCount = positives.size();
Collections.sort(negatives);
Collections.sort(positives);
Map<Integer, Integer> countMap = new HashMap<>(arr.length);
Map<Integer, Long> sumMap = new HashMap<>(arr.length);
long totalSum = positiveSum + (negativeSum * -1);
countMap.put(0, negativeCount);
sumMap.put(0, totalSum);
if (positiveCount != 0) {
long tmpTotalSum = totalSum;
int tmpNegativeCount = negativeCount;
int increment = negativeCount - positiveCount;
int index = 0;
for (int i = 1; i <= positives.get(positiveCount - 1) + 1; i++) {
while (index != positives.size() && positives.get(index) - i == -1) {
tmpNegativeCount++;
increment += 2;
index++;
}
tmpTotalSum += increment;
countMap.put(i * -1, tmpNegativeCount);
sumMap.put(i * -1, tmpTotalSum);
}
}
if (negativeCount != 0) {
long tmpTotalSum = totalSum;
int tmpNegativeCount = negativeCount;
int increment = positiveCount - negativeCount;
int index = negativeCount - 1;
for (int i = 1; i <= (negatives.get(0) - 1) * -1; i++) {
int incrementNxt = 0;
while (index != -1 && negatives.get(index) + i == 0) {
tmpNegativeCount--;
incrementNxt += 2;
index--;
}
tmpTotalSum += increment;
increment += incrementNxt;
countMap.put(i, tmpNegativeCount);
sumMap.put(i, tmpTotalSum);
}
}
int maxNegative = positiveCount != 0 ? (positives.get(positiveCount - 1) + 1) * -1 : 0;
int maxPositive = negativeCount != 0 ? ((negatives.get(0) - 1)) * -1 : 0;
int totalCount = positiveCount + negativeCount;
long accumulatedTotal = 0;
for (int i = 0; i < queries.length; i++) {
accumulatedTotal += queries[i];
if (accumulatedTotal >= maxNegative && accumulatedTotal <= maxPositive) {
results[i] = sumMap.get((int)accumulatedTotal);
} else if (accumulatedTotal < maxNegative) {
long extra = maxNegative - accumulatedTotal;
results[i] = sumMap.get(maxNegative) + countMap.get(maxNegative) * extra;
} else {
long extra = accumulatedTotal - maxPositive;
results[i] = sumMap.get(maxPositive) + (totalCount - countMap.get(maxPositive)) * extra;
}
}
return results;
}