PSHTRG - Editorial
<h1>PROBLEM LINK:</h1>
<p>
<a href="http://www.codechef.com/MARCH18A/problems/PSHTRG">Contest</a><br>
href="http://www.codechef.com/MARCH18A/problems/PSHTRG">Div1</a>, <a href="http://www.codechef.com/MARCH18B/problems/PSHTRG">Div2</a><br>
<a href="http://www.codechef.com/problems/PSHTRG">Practice</a>
</p>
<p>
<strong>Author:</strong> <a href="http://www.codechef.com/users/fekete">Ivan Fekete</a><br>
<strong>Tester:</strong> <a href="http://www.codechef.com/users/triveni">Triveni Mahatha</a><br>
<strong>Editorialist:</strong> <a href="http://www.codechef.com/users/adkroxx">Adarsh Kumar</a>
</p>
<h1>DIFFICULTY:</h1>
<p>Medium</p>
<h1>PREREQUISITES:</h1>
<p>Segment tree</p>
<h1>PROBLEM:</h1>
You are given an array with $N$ elements. You need to support two types of operations on this array. First one is point update. For the second operation, you will be given query range $l,r$ and you need to find the maximum possible perimeter of a triangle with non-zero area whose sides are $A_x, A_y, A_z$, where $l \le x < y < z \le r$. If no triangle can be formed, you just need to output $0$.
<h1>QUICK EXPLANATION:</h1>
<p>Build a segment tree where each node stores largest $K$ elements from the interval. Value of $K$ for given constraint will be around $45$. Update function on the tree can now be supported in $O(KlogN)$.</P>
<p><strong>Claim:</strong> For a given range, triangle with maximum perimeter can be formed using largest $K$ elements from that interval. Answer will be 0, only for the case, when there will be less than $K$ elements in the interval and no triangle formation is possible.</p>
<p>You can query for largest $K$ elements in $O(KlogN)$. Finding the triangle with maximum perimeter afterward is relatively easy and procedure for the same can be found in detailed explanation.</p>
<h1>EXPLANATION:</h1>
<p>Let's try to solve a simpler version first.</p>
<h3>Solve a simple version first:</h3>
In this version, you are given an array of $N$ integers and you need to find the maximum possible perimeter of a triangle.<br>
To solve this problem, first, we sort our array in non-ascending order. Next, we iterate over each $ A[i] $ (where $ 1 \le i < N-1 $ ) and fix the longest side, $ c = A[i] $. To satisfy the condition $ a+b>c $ and maximize $ a+b+c $, we must choose $ b = A[i+1] $ and $ a = A[i+2] $. $a+b+c$ will be the largest perimeter for minimal $i$ satisfying the condition $a+b>c$. The answer will be $0$ if no such $i$ exist.<br>
<strong>Claim:</strong> If $N>K$, answer always exist and can be found using largest $K$ elements, i.e. $ i \le K $. Here $ K = O(log_{\phi}(\sqrt{5}.MAX))$, where $\phi = \frac{1+\sqrt{5}}{2}$ and $MAX$ is the maximum value which can be present in the array.<br>
<strong>Proof:</strong> Lets say you keep adding elements in an array in increasing order such that no triangle formation is possible at any instant. Say there are $r$ elements currently in the array, when you add $(r+1)^{th}$ element, it must not satisy triangle inequality with any elements already present in the array. Hence we can write,<br>
<center>$A[r+1] \ge A[r]+A[r-1]$</center><br>
If we keep on adding elements in this manner, we will end up on <a href="https://en.wikipedia.org/wiki/Fibonacci_number">fibonacci sequence</a>. Fibonacci numbers grows very fast and soon they will exceed the maximum value that can be present in the array. If we do not exceed the maximum value that can be present in the array, triangle can definitely be formed using $K$ elements. You can compute the exact value of $K$, but we will just use approximation here for our purpose:<br><br>
<center>$fib(K) > MAX$<br>
$\Rightarrow \frac{\phi^K}{\sqrt{5}} > MAX$<br>
$\Rightarrow K > log_{\phi}(\sqrt{5}.MAX)$</center>
<strong>Conclusion:</strong> For our original purpose, we will only need largest $K$ elements from the query range. We need a Data Structure that can support point update and can report largest $K$ elements from any query range in logarithmic time complexity or similar. For current constraints $K = 45$.
<h3>Using segment tree for our purpose</h3>
<p>We can perform our required operation with the help of segment tree. In each node of segment tree, you need to store largest $K$ elements from that interval. If size of interval is less than $K$ then store all elements from that interval.</p>
<p>Merge function for two nodes can be implemented in a manner similar to merge sort algorithm. Merging of two nodes can be done in $O(K)$. For each update/query, you will need to change/visit atmax $logN$ nodes. Hence the time complexity for each update/query will be $O(KlogN)$. For more implementation details, you can have a look at attached solutions.</P>
<h1>Time Complexity:</h1>
<p>$O(Q.K.logN)$ </p>
<h1>AUTHOR'S AND TESTER'S SOLUTIONS</h1>
<p><a href="http://www.codechef.com/download/Solutions/MARCH18/Setter/PSHTRG.cpp">Setter's solution</a><br>
<a href="http://www.codechef.com/download/Solutions/MARCH18/Tester/PSHTRG.cpp">Tester's solution</a><br>
</p>