// Basic Kadane's - returns max sum
long long kadane(vector<int>& arr) {
long long maxSoFar = arr[0], maxEndingHere = arr[0];
for (int i = 1; i < arr.size(); i++) {
maxEndingHere = max(1LL * arr[i], maxEndingHere + arr[i]);
maxSoFar = max(maxSoFar, maxEndingHere);
}
return maxSoFar;
}
// Kadane's with subarray indices
array<long long, 3> kadaneWithIndex(vector<int>& arr) {
long long maxSoFar = arr[0], maxEndingHere = arr[0];
int start = 0, end = 0, s = 0;
for (int i = 1; i < arr.size(); i++) {
if (maxEndingHere + arr[i] < arr[i]) {
maxEndingHere = arr[i];
s = i;
} else {
maxEndingHere = maxEndingHere + arr[i];
}
if (maxEndingHere > maxSoFar) {
maxSoFar = maxEndingHere;
start = s;
end = i;
}
}
return {maxSoFar, start, end};
}
// Circular array maximum sum
long long circularKadane(vector<int>& arr) {
long long normalSum = kadane(arr);
if (normalSum < 0) return normalSum;
long long totalSum = 0;
for (int i = 0; i < arr.size(); i++) {
totalSum += arr[i];
arr[i] = -arr[i];
}
long long circularSum = totalSum + kadane(arr);
return max(normalSum, circularSum);
}