using System; using System.Collections.Generic; using System.Linq; namespace AnotherReplayReader.Utils { public record TimeIndexedPrefixSums(List Times, List PrefixSums) { public void Add(TimeSpan time, int value) { if (Times.Count > 0 && time < Times.Last()) { throw new ArgumentException("Time must be added in non-decreasing order."); } Times.Add(time); PrefixSums.Add((PrefixSums.LastOrDefault()) + value); } public int Query(TimeSpan start, TimeSpan end) { var times = Times; var prefix = PrefixSums; int startIndex = LowerBound(times, start); int endIndex = UpperBound(times, end); if (startIndex >= times.Count || endIndex < 0 || startIndex > endIndex) { return 0; } int result = prefix[endIndex]; if (startIndex > 0) { result -= prefix[startIndex - 1]; } return result; } public int GetTotal() { return PrefixSums.LastOrDefault(); } public static int LowerBound(List arr, TimeSpan target) { int left = 0, right = arr.Count; while (left < right) { int mid = left + (right - left) / 2; if (arr[mid] < target) { left = mid + 1; } else { right = mid; } } return left; } public static int UpperBound(List arr, TimeSpan target) { int left = 0, right = arr.Count; while (left < right) { int mid = left + (right - left) / 2; if (arr[mid] <= target) { left = mid + 1; } else { right = mid; } } return left - 1; } } }