** Beep Beep **
Unofficial Editorial here.
Been a long time since last time I wrote an editorial unofficially, so thought to give it a try again.
I won’t be following the standard editorial style because My editorial, My rules
Do not expect an awesome short and interesting editorial because I’ll try to make it long and boring.
So, Let’s get started with the problem TSEQ (the problem i liked the most from august challenge, it’s elegant) (which i assume you have read statement here because I’m not gonna explain statement too).
Time for a combinatorics class first!
-
What’s the number of ways to select K distinct elements in the range (A, B) excluding A and B assuming A +1 < B.
It’s ^{(B-A-1)}C_{K} since we can select any combination of K elements from B-A-1 choices. -
What’s the number of ways to select K elements with repetition allowed in the range [A, B].
It’s ^{(B-A+1 + K-1)}C_K, explained here as I am not explaining.
End of combinatorics class.
Let’s assume we are not given a tree, but an array, and we have to answer the same queries for subarrays.
There are four types of queries, strictly increasing, strictly decreasing, non-decreasing and non-increasing and we have to answer the query for subarray [u, v] and values [A, B]. (Note that for this problem, subarray [u, v] is not same as [v, u].)
But, we can notice that number of ways to get the strictly increasing sequence in subarray [u, v] is same as the number of ways to get strictly decreasing sequence in subarray [v, u]. That’s it, we can just swap the ends of the subarray, whenever we get a query for decreasing or non-increasing sequence.
Let’s answer queries now.
If there is any position in subarray [u, v] containing value smaller than A or larger than B, the answer is already 0. Also, if the sequence is not strictly-increasing/non-decreasing, then too answer is 0.
Considering the subarray [u, v] and value range [A, B], It looks something like following. (… means any number of -1 present).
-1 -1 ... v1 -1 -1 ... v2 -1 -1 ... v3 -1 -1... vk -1 -1 ....
Where for each 2 \leq i \leq k, v_{i-1} < v_i or v_{i-1} \leq v_i depending upon query.
Calling C_i as the number of occurrences of -1 after V_i and C_0 as the number of occurrences of -1 at the start. Let’s call these blocks of -1 as sections.
Assume f(x, y, k, strict) gives the number of ways to select k elements from x to y considering strict, or non-strict inequality.
We can see, we can fill each section independently of each other, so the answer is the product of the number of ways to fill each section.
For non-decreasing sequence, The number of ways to fill the section with k occurrences of -1 and values within range [L, R] is same as the number of ways to select K elements with repetition allowed in the range $[L, R]. Remember Combinatorics class? The range of value can be determined from v_i by being smart.
A similar conclusion can be drawn for a strictly increasing sequence.
Now, considering the very first and very last section, the lower limit and upper limit for sections can be found using A and B given in the query.
But hey! didn’t we calculate the number of ways to fill all sections except border sections without A and B, so let’s precompute them all. Doing for all subarrays is expensive, so a data structure class is necessary, using any range structure such as segment tree would work. But we also need the information about the number of -1 at start and end of array. But we are segment-tree experts, right, and we have solved this problem, so we can make a special node storing all required info and answer queries.
Too Sleepy to take Data structure class now. Suggest topics for a class, and I will take it.
All done, right?
But we are given a tree, how we are supposed to use this array problem in the tree. Turns out, we need another trick under our sleeve, Heavy Light Decomposition Turns out, it answers all our doubts to reduce a path in the tree into an array problem.
Implementation can be tough, but the price of 100 points has never been less. For HLD, take care whether for this node, we are moving up or down (Path from u to v → Path moving up from u to lca(u, v) and then moving down from lca(u, v) to v).
That’s all for today folks. I’ll try to read any suggestions you offer at the pleasure of myself.
All done within an hour (excluding solving time, which is ofcourse, in days )
\sout {PS: Someone challenged me that I cannot get more than 25 likes on an editorial. Can you guys help me prove him wrong? Thanks!}
UPDATE: Challenge is up, Defeat conceded by challenger.
EDIT: Adding details about segment tree node, each node represent some segment in segment tree.
Each node contains following data (as per my solution linked below).
contains > boolean whether current range contains any value other than -1.
Left → if contains is true, this denote smallest value other than -1 in current segment
Right → if contains is true, this segment denote largest value other than -1 in current segment
lCount → if contains ia true, then this contains the number of -1 as prefix.
If false, it denotes the number of -1 in range.
rCount → if contains is true, this stores the number of -1 as suffix.
S → number of ways to fill all -1 except prefix and suffix such that the sequence is strictly increasing.
NS → number of ways to fill all -1 except prefix and suffix such that the sequence is non-decreasing.
Refer the node in this solution (ignore TLE, that’s something wrong in lifting). You can view my AC submission, but that is too messy. See that at your own risk
Important part in this solution is merge function, and the eval function in node class.