Quantcast
Channel: CodeChef Discuss - latest questions
Viewing all articles
Browse latest Browse all 39796

MARRAYS - Editorial

$
0
0

PROBLEM LINK

Practice
Contest

Author:Dmytro Berezin
Tester:Alexey Zayakin
Editorialist:Jakub Safin

DIFFICULTY

EASY-MEDIUM

PREREQUISITIES

dynamic programming

PROBLEM

You're given $N$ arrays $A_1,\dots,A_N$; the $i$-th array has length $M_i$. You're allowed to cyclically shift any array; you may perform this operation any number of times. Compute the maximum possible value of $\sum_{i=1}^{N-1} i\left|A_i\lbrack M_i\rbrack-A_{i+1}\lbrack 1\rbrack\right|$ after performing zero or more cyclic shifts.

QUICK EXPLANATION

Dynamic programming computing the maximum partial sums $\sum_{j=2}^i (j-1)\left|A_{j-1}\lbrack M_{j-1}\rbrack -A_j\lbrack 1\rbrack\right|$ for each possible $A_i\lbrack 1\rbrack$ (each cyclic shift of each array $A_i$).

EXPLANATION

Let's imagine we knew the optimal cyclic shift of the array $A_i$. The central observation is that the optimal cyclic shifts of the previous $i-1$ arrays and the next $N-i$ arrays are independent - of course, they both depend on $A_i\lbrack 1\rbrack$ and $A_i\lbrack M_i\rbrack$, but not on each other.

That means we can compute the maximum sum from arrays $A_{1..i}$ for each possible cyclic shift of $A_i$ - if we shifted $A_i$ from the input by $s_i$, so that $A_i\lbrack s_i+1\rbrack$ becomes $A_i\lbrack 1\rbrack$, let's call that maximum possible sum $S_{i,s_i}$ - and use dynamic programming to compute all $S_{i,j}$ from the known values of $S_{i-1,j}$.

The initial condition is naturally $S_{1,j}=0~\forall j$, since there are 0 terms in that sum. For $i > 1$, assume we've computed all values $S_{i-1,j}$; we can write a general expression using these values and the input arrays: $$ S_{i,s_i} = \mathrm{max} ( S_{i-1,j} + (i-1)\left|A_i\lbrack s_i+1\rbrack -A_{i-1}\lbrack j\rbrack\right| )\quad \forall~0 \le j < M_{i-1}\,, $$ where we're using the fact that if the array $A_{i-1}$ was shifted by $j=s_{i-1}$, then $A_{i-1}\lbrack s_{i-1}+1\rbrack$ becomes its first element, so $A_{i-1}\lbrack s_{i-1}\rbrack$ becomes its last element (we're also using the convention $A_{i-1}\lbrack 0\rbrack=A_{i-1}\lbrack M_{i-1}\rbrack$).

Usually, working with absolute values directly is complicated. It's a good idea to split the $\mathrm{max}()$ into 2 cases based on which of the numbers $A_i\lbrack s_i+1\rbrack, A_{i-1}\lbrack j\rbrack$ is greater, compute the separate maxima and take their maximum, but there's a trick we can use here: $|x|=\mathrm{max}(x,-x)$, so $$ \mathrm{max} ( S_{i-1,j} + (i-1)\left|A_i\lbrack s_i+1\rbrack-A_{i-1}\lbrack j\rbrack\right| ) = \mathrm{max} \left\lbrack \\ \mathrm{max} ( S_{i-1,j} + (i-1)\left(A_i\lbrack s_i+1\rbrack-A_{i-1}\lbrack j\rbrack\right) )\quad \forall~j, \\ \mathrm{max} ( S_{i-1,j} + (i-1)\left(-A_i\lbrack s_i+1\rbrack+A_{i-1}\lbrack j\rbrack\right) ) \quad \forall~j \\ \right\rbrack \,. $$ In other words, we can compute the maxima for both possible signs and just take their maximum afterwards - the wrong sign will always give a $\le$ number than the right one, so it won't affect the result.

This trick is fairly common when you're asked to compute the maximum of a function involving absolute values, e.g. in a grid with Manhattan distances, and simplifies the code considerably. Note that it fails if you need to compute a minimum instead.

Now let's get back to our problem. It's not very hard to compute the maxima we need now, since we can write $$ \mathrm{max} ( S_{i-1,j} + (i-1)\left(A_i\lbrack s_i+1\rbrack-A_{i-1}\lbrack j\rbrack\right) ) = \mathrm{max} ( S_{i-1,j} - (i-1)A_{i-1}\lbrack j\rbrack ) + (i-1)A_i\lbrack s_i+1\rbrack \,; $$ the term with the maximum doesn't depend on $s_i$ or $A_i$ and since we already know all $S_{i-1,j}$, we can compute it in $O(M_{i-1})$ time and call it $m_1$. Similarly, we get $$ \mathrm{max} ( S_{i-1,j} + (i-1)\left(-A_i\lbrack s_i+1\rbrack+A_{i-1}\lbrack j\rbrack\right) = \mathrm{max} ( S_{i-1,j} + (i-1)A_{i-1}\lbrack j\rbrack ) - (i-1)A_i\lbrack s_i+1\rbrack \,, $$ where the first term with the maximum can be computed just as easily; let's call it $m_2$. The final formula is $$ S_{i,s_i} = \mathrm{max} ( m_1+(i-1)A_i\lbrack s_i+1\rbrack, m_2-(i-1)A_i\lbrack s_i+1\rbrack ) \,. $$ If we use it, we can compute $S_{i,s_i}$ for all $0 \le s_i < M_i$ in $O(M_i)$ time.

This way, we can compute all the sums $S_{i,j}$ for increasing $i$; to get the answer to the problem, we need to take $\mathrm{max} (S_{N,j})$ over all $0 \le j < M_N$.

For a test case with $\sum M_i = N$, this algorithm then runs in $O(N)$ time and $O(N)$ memory.

AUTHOR'S AND TESTER'S SOLUTIONS

Setter's solution
Tester's solution
Editorialist's solution


Viewing all articles
Browse latest Browse all 39796

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>