/** * This submission gets wrong answer because it does not consider the * removal operation. * * @author Finn Lidbetter */ import java.util.* val MAX_EXP = 50 fun main(args: Array) { val n = readLine()!!.toInt(); val arr = readLine()!!.split(" ").map{ it -> it.toLong() } val exps = IntArray(n) for ((index, value) in arr.withIndex()) { var curr = value var exp = 0 while (curr > 1) { curr = curr shr 1 exp++ } exps[index] = exp } // val prefixSum = arr.runningFold(0L) { sum, item -> sum + item } var prefixSum = Array(arr.size + 1){ 0L } for (index in 0..arr.size - 1) { prefixSum[index + 1] = prefixSum[index] + arr[index] } var largestMergedSum = 0L // dp[i][j] is True iff we can reduce values in [i,j] to their sum. var dp = Array(n){ BooleanArray(n) } for (i in 0..n-1) { dp[i][i] = true if (arr[i] > largestMergedSum) { largestMergedSum = arr[i] } } for (intervalLen in 0..n-1) { for (currIntervalLo in 0..n-1) { val currIntervalHi = currIntervalLo + intervalLen if (currIntervalHi >= n) { break } if (!dp[currIntervalLo][currIntervalHi]) { continue } val targetSum = prefixSum[currIntervalHi + 1] - prefixSum[currIntervalLo] if (currIntervalLo > 0) { // Can we merge this interval with something to the left? var searchLo = 0 var searchHi = currIntervalLo - 1 var foundIndex = -1 while (searchLo <= searchHi) { var mid = (searchLo + searchHi) / 2 val sum = prefixSum[currIntervalLo] - prefixSum[mid] if (sum == targetSum) { foundIndex = mid break } else if (sum < targetSum) { searchHi = mid - 1 } else { searchLo = mid + 1 } } if (foundIndex != -1 && dp[foundIndex][currIntervalLo - 1]) { dp[foundIndex][currIntervalHi] = true if (targetSum * 2 > largestMergedSum) { largestMergedSum = targetSum * 2 } } } if (currIntervalHi < n-1) { // Can we merge this interval with something to the right? var searchLo = currIntervalHi + 1 var searchHi = n - 1 var foundIndex = -1 while (searchLo <= searchHi) { val mid = (searchLo + searchHi) / 2 val sum = prefixSum[mid + 1] - prefixSum[currIntervalHi + 1] if (sum == targetSum) { foundIndex = mid break } else if (sum < targetSum) { searchLo = mid + 1 } else { searchHi = mid - 1 } } if (foundIndex != -1 && dp[currIntervalHi + 1][foundIndex]) { dp[currIntervalLo][foundIndex] = true if (targetSum * 2 > largestMergedSum) { largestMergedSum = targetSum * 2 } } } } } println(largestMergedSum) }