private void Build(int treeArrayIndex, int segmentStartIndex, int segmentEndIndex) { if (segmentStartIndex == segmentEndIndex) { _treeArray[treeArrayIndex] = new MaximumSumQueryValue(_sourceArray[segmentStartIndex]); return; } int leftChildTreeArrayIndex = 2 * treeArrayIndex + 1; int rightChildTreeArrayIndex = leftChildTreeArrayIndex + 1; Build(leftChildTreeArrayIndex, segmentStartIndex, (segmentStartIndex + segmentEndIndex) / 2); Build(rightChildTreeArrayIndex, (segmentStartIndex + segmentEndIndex) / 2 + 1, segmentEndIndex); _treeArray[treeArrayIndex] = _treeArray[leftChildTreeArrayIndex].Combine(_treeArray[rightChildTreeArrayIndex]); }
public MaximumSumQueryValue Combine(MaximumSumQueryValue rightAdjacentValue) => new MaximumSumQueryValue { // The sum is just the sum of both. Sum = Sum + rightAdjacentValue.Sum, // The maximum sum either intersects both segments, or is entirely in one. MaximumSum = Math.Max( MaximumRightStartingSum + rightAdjacentValue.MaximumLeftStartingSum, Math.Max(MaximumSum, rightAdjacentValue.MaximumSum)), // The maximum left starting sum starts at the left, and may or may not cross into the right. MaximumLeftStartingSum = Math.Max( Sum + rightAdjacentValue.MaximumLeftStartingSum, MaximumLeftStartingSum), // The maximum right starting sum starts at the right, and may or may not cross into the left. MaximumRightStartingSum = Math.Max( rightAdjacentValue.Sum + MaximumRightStartingSum, rightAdjacentValue.MaximumRightStartingSum) };