Interval Dynamic Programming Strategy for Maximum Sequence Value
The objective is to determine the highest possible integer achievable by merging adjacent equal values in a sequence. When two adjacent numbers share the same value $v$, they can be combined into a single number with value $v+1$. This process repeats until no further merges are possbile or the desired maximum is reached.
To solve this efficiently, an interval dynamic programming approach is suitable given the constraint $N \le 248$. Define a state table where dp[i][j] represents the single value obtained if the subarray from index $i$ to $j$ is completely merged. If the range cannot be reduced to a single number, the value remains 0.
Initialization sets dp[i][i] to the input sequence values. The algorithm iterates through all posssible subarray lengths. For each range [i, j], it checks every possible split point k. If the left segment [i, k] and the right segment [k+1, j] both merge into the same non-zero value, the current range [i, j] can merge into that value plus one. Throughout this process, track the global maximum value encountered.
The time complexity is $O(N^3)$ due to the three nested loops (length, start index, split point), which fits with in the limits for $N \approx 250$. Space complexity is $O(N^2)$ for the DP table.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int size;
if (!(cin >> size)) return 0;
vector<int> initial_values(size);
for (int i = 0; i < size; ++i) {
cin >> initial_values[i];
}
// dp[i][j] stores the merged value of range [i, j], or 0 if impossible
vector<vector<int>> dp(size, vector<int>(size, 0));
int max_val = 0;
// Base case: single elements
for (int i = 0; i < size; ++i) {
dp[i][i] = initial_values[i];
max_val = max(max_val, dp[i][i]);
}
// Iterate over subarray lengths
for (int span = 2; span <= size; ++span) {
// Iterate over start index
for (int start = 0; start <= size - span; ++start) {
int end = start + span - 1;
// Iterate over split point
for (int pivot = start; pivot < end; ++pivot) {
int left_val = dp[start][pivot];
int right_val = dp[pivot + 1][end];
if (left_val > 0 && left_val == right_val) {
int merged = left_val + 1;
dp[start][end] = max(dp[start][end], merged);
max_val = max(max_val, merged);
}
}
}
}
cout << max_val << endl;
return 0;
}