SNTEMPLE - Editorial



Author: admin2
Testers: Hasan Jaddouh
Editorialist: Pawel Kacprzak




Binary search, precomputation


Let a magic sequence of order m, denoted also by magic(m), be a sequence of a integers starting from 1 and increasing by 1 up to m and then decreasing from m to 1. For example, the magic sequence of order 5 is: 1, 2, 3, 4, 5, 4, 3, 2, 1. Notice that magic(m) has length 2 \cdot m - 1.

Given an array of h of n positive integers, denoting consecutive blocks, you want to perform the smallest number operations of reducing the high of a selected block by 1 in such a way that after all operations are performed, there exists exactly one magic sequence in h and all elements of h not included in the magic sequence are 0.


The problem can be reformulated as follows: find the largest possible integer m, such that there can be formed a magic sequence of order m in h. You might wonder why this problem is equivalent to the one asked in the original statement. Well, let s be the sum of all integers in h. In order to form the resulting sequence magic(m) in h and set all elements in h not included in this sequence to 0, we have to perform s - m \cdot (m+1) - m = s - m^2 operations, because the sum of heights in magic(m) is m^2. Since we want to minimize the number of performed operations, we want to maximize m.

The second crucial observation is that if we can form a sequence magic(m) in h, then for each k < m, we can also for a sequence magic(k) in h. This follows from the fact that in order to transform sequence magic(m) to magic(m-1), the only thing to do is to subtract one from each of its elements and remove the left-most and the right-most elements.

Based on the above two observations, we can use binary search to find the largest m, such that sequence magic(m) can be formed in h. The lower bound for binary search should be set to 1, and the upper bound can be set to for example n, but one can also compute the more exact upper bound, although it doesn’t matter much.

Now, how for a fixed m find out if a sequence magic(m) can be formed in h, and do it in linear time?

One possible solution is to compute two boolean arrays of size n:

L[i] := true if and only if the sequence 1, 2, \ldots, m can be formed in h[i-m+1], h[i-m+2], \ldots, h[i].
R[i] := true if and only if the sequence m, m-1, \ldots, 1 can be formed in h[i], h[i+1], \ldots, h[i+m-1].

Then, sequence magic(m) can be formed in h if and only if there exists i, 1 \leq i \leq n, such that both L[i] and R[i] are true. Thus the problem is reduced to computing arrays L and R.

Let’s take a closer look on how to compute array L. Computing array R is based on the same idea.

First of all, let’s set all entries in L to false. The idea is to iterate over h from left to right (right to left if you want to compute R) while updating variable k denoting the length of the longest sequence 1, 2, 3, \ldots, k ending in the current element, where k is at most m. The below pseudocode illustrates the approach:

k = 0
for i = 1 to n:
    if h[i] >= k+1:
        k += 1
        if k == m:
            L[i] = true
            k -= 1
        k = h[i]

The above idea is based on the fact that if we have a sequence 1, 2, \ldots, k ending in i-1, then if h[i] is at least k+1 we can extend the sequence by one, and if h[i] is at most k, then the best we can do is to set k to h[i], because a sequence 1, 2, \ldots, k ending at index i-1 can be transformed to a non-longer sequence 1, 2, \ldots, h[i] ending at index i if h[i] \leq k.

Since the computing of arrays L and R takes O(n) time, and the range over we perform binary search has length O(n), the total time complexity is O(n \cdot \log(n)).

As it was pointed out with the comments, the above method can be improved to O(n) solution by avoiding binary search. The idea is to compute arrays L and R at the beginning, without specifying m. We define L[i] (and similarly R[i]) as the maximum length of sequence 1, 2, \ldots ending in i, and compute it as follows:

k = 0
for i = 1 to n:
    if h[i] >= k+1:
        k += 1
        k = h[i]
    L[i] = k

Then, after computing arrays L and R, we know that the maximum m for which magic sequence of order m exists is \max\limits_{1 \leq i \leq n} \min(L[i], R[i])


Setter’s solution can be found here.
Tester’s solution can be found here.
Editorialist’s solution can be found here.


There is some error with the links, please fix them.

Not able to access editorial

@pkacprzak can’t able to open the editorials…“Access denied error”

access denied for links of the solution

we can also do it in O(n) by maintaining left and right array and then calculating the answer.
solution link


Here is a simple \mathcal{O}(n) solution. As mentioned in the editorial, the problem can be restated as simply finding the largest temple possible. Imagine breaking the temple into two triangles, with the centre overlapping. For example, temple [1, 2, 3, 2, 1] becomes triangle [1, 2, 3] and [3, 2, 1]. Now, for each index i calculate the maximum height of a left-triangle whose highest point is i. Let this be L[i], then L[i+1] is simply min(L[i]+1, h[i+1]). Hence L[i] can be computed for all indices in linear time. Do the same for the right-triangles, using another array R, where R[i-1] will similarly be min(R[i]+1, h[i-1]). Then for each index i, the largest temple that has its peak at i is min(L[i], R[i]). The maximum of this value among all indices will give you the largest temple possible in whole array. The number of operations needed to obtain this temple is just the total number of blocks in the temple subtracted from the sum of the array h.
Here is my

[1] for reference.


Yup. O(N) solution.

Nice, the same idea as mine, but with better complexity avoiding binsearch at all


Solution in python3.4 : SNTEMPLE


Don’t worry, they’ll be added soon. I don’t have access to add them by myself.

Can someone explain o(n) sol in detail with comments

Would be a great help
Appreciate it.
Thanks in advance.

Hey we(my team) came up with a very easy solution also of complexity O(n),
What we did first checked the first and last element of h[n] should be equal to zero or one only, in case it is larger than it , make h[i] equal to 1, then start the iteration from second to last element while taking input and in case h[i]>h[i-1]+1 => h[i]=h[i-1]+1 because in case this strip is used its length must be h[i-1]+1 or less than it, otherwise h[i]= original input , just continue this process to whole input but meanwhile sum up all the original input in a variable S which is total number of blocks in mountain .
But process doesn’t ends there do this in same manner in reverse direction, but first do the process for h[n-1](last element ) same as we did for h[0] then do the whole process in opposite direction i.e. iterate the array h[N] in opposite direction if h[i]>h[i+1]+1, then again h[i]=h[i+1]+1.
What all this process will do that it will trim the mountain in which each peak leads to the formation of a mountain i.e. all the possible mountains could be found their and each block could be used to create a mountain.
Then find the highest peak height which also could be find while second iteration or separately.
Then find the number of blocks in this mountain with that highest height i.e. (maximum height)^2 =>(more clearly ((m.h.+1) * m.h)/2 + ((m.h.-1) * m.h)/2 ).
Now just subtract it from that sum S .
Here is my solution ++> click heret
Remove the comments in this code and run this in codechef Id you can easily understand the whole magic.

@pkacprzak Can you please explain why we have to perform s−m⋅(m+1)−m operations? How did that factor came?

@chari407 sum of magic(m)= m * m ,lets see how , sum of [1…m]=m * (m+1)/2 ,as sum[magic(m)]=2 * sum[i…m]-m (you can see m gets added twice in 2 * sum[1…m] ,so a subtaction of m is needed that’s why m is substracted)
so sum[magic(m)]=m * m+ m-m=m * m so required operations= s - m * m;

1 Like

Thanks mate.

@genius007 , bhambhu on fire.

How are we finding m using binary search ? Please explain ?

Yup me tooo y s-m.m+1-m

@meooow Can you please elaborate your solution approach? , I am new to this CP field , please bear with me