For every element of the sequence with index i
we will calculate F(i, high)
and F(i, low)
, where F(i, high)
equals to the biggest sum of the subsequence with wanted characteristics that ends with the i
-th element and this element is a "high peak". (I'll explain mainly the "high" part, the "low" part can be done similarly). We can calculate these functions using the following relations:

The answer is maximal among all F(i, high)
and F(i, low)
values.
That gives us a rather simple dynamic programming solution with O(n^2)
time complexity. But we can go further.
We can optimize a calculation of max(F(j,low))
part. What we need to do is to find the biggest value among previously calculated F(j, low)
with the condition that a[j] < a[i]
. This can be done with segment trees.
First of all, we'll "squeeze" our initial sequence. We need the real value of the element a[i]
only when calculating the sum. But we need only the relative order of the elements when checking that a[j]
is less than a[i]
. So we'll map every element to its index in the sorted elements array without duplicates. For example, sequence a = 2 18 6 7 8 2 10
will be translated to b = 0 5 1 2 3 0 4
. This can be done in O(n*log(n))
.
The biggest element of b
will be less than n
, as a result, we can build a segment tree on the segment [0, n]
with every node containing the biggest sum within the segment (we need two segment trees for "high" and "low" part accordingly). Now let's describe the step i
of the algorithm:
- Find the biggest sum
max_low
on the segment [0, b[i]-1]
using the "low" segment tree (initially all nodes of the tree contain zero).
F(i, high)
is equal to max_low + a[i]
.
- Find the biggest sum
max_high
on the segment [b[i]+1, n]
using the "high" segment tree.
F(i, low)
is equal to max_high + a[i]
.
- Update the
[b[i], b[i]]
segment of the "high" segment tree with F(i, high)
value recalculating maximums of the parent nodes (and [b[i], b[i]]
node itself).
- Do the same for "low" segment tree and
F(i, low)
.
Complexity analysis: b
sequence calculation is O(n*log(n))
. Segment tree max/update operations have O(log(n))
complexity and there are O(n)
of them. The overall complexity of this algorithm is O(n*log(n))
.