Contest 20060 en
Contest 20060 en
Problem A. Cities
Let’s assume that we are at point p now. We have two options.
1) Go to t directly, paying extra |p - t| ∗ap money.
2) Go to another "optimal"point. There are two choices for that. Either it is minimum r such that ar < ap
and r > p, or maximum l such that al < ap and l < p.
So run Dijkstra, maintaining minimum distance. Update answer by the first option. Or go to the next
optimal point paying av ∗ dist(r − p or p − l) money. We are multiplying av because each time we are
going to the index with a lower value. Total complexity is O(nlogn).
The graph you get is a DAG, so simple dp is enough. Total complexity is O(n).
Homework: Calculates answers for every t in O(n).
Problem B. Potatoes
Build a binary tree. If vertex contain array a1 , a2 ... left child a1 , a3 .., right child a2 , a4 .... Root vertex
contain initial array.
Array bad if it contains two equal elements.
For every query: ans = countof x ∗ x + countof y ∗ y. Notice countof x = countof y + 1. We will calculate
countof x. countof x equal to a number of bad vertexes in the binary tree.
If we fix the right border of the interval for every vertex we can compute the Li -left border such that
every interval with such right border and left border at most Li is bad. countof x equal to a number of
l <= Li .
Every element in at most log(n) vertexes in the binary tree. So we will re-calculate Li only for log(n)
vertexes. To calculate a number of l <= Li we can use segment tree or sqrt decomposition. Total
√
complexity is O(nlog 2 n + qlogn) or O(nlogn + q n).
Problem C. Chips-dips
After each operation number of inversions doesn’t change.
If i < j (pi = 1, pj = n) call permutations good, otherwise bad.
The answer exists if the number of inversions is the same and both permutations are good or bad.
If the permutation good/bad we can transform it into every permutations with pn = n/1 and same
number of inversion. For every triple pi−1 , pi , pi+1 (pi = n/1) always exist one operation. We will reapat
this operations until pn = n/1. It can be proved that the number of operations is at most a polynomial
of the second degree in n. Call this operations take_out
Now look to other elements. If they bad but initial permutations can be transformed to other with
pn = n/1, pn−1 = n − 1/n we need make him good using pn . Call this operations f ix.
Assume initial permutations is good and after take_out(n) and take_out(n − 1) we got permutations
...c, a, b, n − 1, 1, n. If a < b we can transform it to ...c, b, a, 1, n − 1, n, otherwise we need to order_suf f ix.
pseudo code:
order_suf f ix(n):
take_out(n)
Page 1 of 4
2021 XVII International Zhautykov Olympiad
,
1. If first n elements is good find i (pi = n) otherwise i (pi = 1)
2. If i = n break
4. take_out(n)
f ix(n):
1. take_out(n)
3. take_out(n − 1)
4. order_suf f ix(n − 2)
solve(n):
1. take_out(n)
3. solve(n − 1):
It can be proved that the number of operations is at most a polynomial of the third degree in n.
Page 2 of 4
2021 XVII International Zhautykov Olympiad
,
Otherwise, k is even and there are exactly 2 ways to color this cycle. We will have k/2 white and k/2 black
numbers. All black numbers should go before all white numbers. And the contribution is (the position of
the first white number) - (the position of the last black number) + 1.
We could try brute forcing all possible separators 1 ≤ t ≤ n, so that all black numbers are in the range
k/2 k/2
[1, t] and all white numbers are in the range [t + 1, n]. There are Ct × Cn−t ways to achieve that. The
order of these halves also does not matter, so we should also multiply by (k/2)!2 .
√
This solution solves for a fixed length k in O(n) time, so exploiting the fact that there are at most O( n)
√
different cycle lengths, we arrive at a O(n n) solution for 81 points.
To get the full score we should get rid of brute forcing the separator. There is a beautiful trick. Let’s
say that separator is just another item between those halves of size k/2. So there are Cnk+1 combinations
in total, where the separator is exactly the k + 1-th item. However, we did not count cases where the
separator is the same as the k-th item. There are Cnk such combinations. So, we have a nice and clean
solution in O(n log n) or O(n) depending on your way of calculating factorial inverses.
Problem E. Rooms
Let’s discuss the greedy solution first. Our current state can be described by the segment of available
rooms (l, r) and our experience xp. Whenever we can open the leftmost or rightmost door and increase
our segment, we should do so, because the constraint ai ≥ 0 ensures it is always optimal. If we cannot
open both doors, we should buy some experience so that at least one of them becomes open and repeat
our process. We stop when we can already escape the house.
The naive implementation solves the problem in O(n2 ) time, which is enough for first two subtasks.
It can be further optimized to solve the problem in O(n · max(bi )) time, which is enough for the fifth
subtask.
For the third subtask, calculate prefix and suffix maximums on b and choose the optimal direction.
For the fourth subtask, the answer is simply max(0, bi − ai ).
Now, let’s come up with a pure mathematical solution using our greedy approach. Say, we want to
calculate the answer for the room i. Imagine our segment of available rooms at some point P is (l, r)
satisfying l ≤ i ≤ r. Then, to extend the segment, we would have to have at least min(bl , br+1 ) − rj=l aj
coins donated. Since our donations accumulate, it is enough to take the maximum over those.
r
X
ansi = maxl≤i≤r (min(bl , br+1 ) − aj )
j=l
Now, there are several approaches leading to the full solution. I will describe the hardest (but
intended) one — divide and conquer. Let’s define a function calc(L, R) which will solve for all segments
within the range (L, R). Let M = (L + R)/2. As usual, we recursively run calc(L, M) and calc(M+1,
R). Now we have to consider all segments connecting both halves. Let’s calculate the suffix sum suff on
a for the first half, and the prefix sum pref on a for the second half.
Focus on the left half. Let the left endpoint of a segment be l ≤ M . Then, we would have to update all
values ansl , . . . , ansM with the value maxM <r≤R (min(bl , br+1 ) − suffl − prefr ). If we let bl ≤ br+1 , we
are maximizing −prefr on the right half. If we let bl > br+1 , we are maximizing br − prefr on the right
half. The equations for the right half are almost identical. All of those values can be easily calculated if
we also do a merge sort on b. Note that without merge sort we would have had a O(n log2 n) solution
for 80 points.
So, we get a not-easy-but-not-that-hard-either full solution in O(n log n) time complexity. There are also
some DSU and stack solutions, which are probably easier to implement and work better in practice (but
whatever).
Page 3 of 4
2021 XVII International Zhautykov Olympiad
,
Problem F. Dendrology
1. n ≤ 1000, q = 0. It is guaranteed that ai = i, bi = i + 1 for all i (1 ≤ i < n).
Given tree is bamboo. Sl,r contains all vertexes between leftmost and rightmost vertexes in bamboo. Fix
l, iterate r and keep leftmost and rightmost vertexes. O(n2 )
2. n ≤ 105 , q = 0. It is guaranteed that ai = 1, bi = i + 1 for all i (1 ≤ i < n).
Given tree is star. Sl,r contains all vertexes in interval and center vertex if interval contains at least two
vertexes. Sl,r = r − l + 1 or r − l + 2. O(n)
3. n ≤ 105 , q = 0. It is guaranteed that ai = i, bi = i + 1 for all i (1 ≤ i < n).
P
Optimization
P for subtask
P 1. To calculate maximum − minimum over all intervals we calculate
maximum and minimum separately. It’s a classic "sum of subarray minimums"problem. O(n)
4. n ≤ 1000, q = 0.
Fix l, iterate r and answer the query which requires the minimal number of size of subtree which contains
all the vertices in the set, after the "add vertices to the set"operation.
We can calculate the distance between two nodes with the LCA algorithm, then when we
order the nodes by dfs order, we can answer the "add vertice"query that adds the vertice
which is numbered s in dfs order, and assume that the previous numbered vertices in dfs
order in the set is vertex t, and next is vertex u, we can get rid of the "add"query that
(thecurrentsizeof thesubtree) + distance(s, t) + distance(t, u) − distance(s, u).
The time complexity of the LCA algorithm is O(logn). O(n2 logn)
5. n, q ≤ 105 . It is guaranteed that ai = i, bi = i + 1 for all i (1 ≤ i < n).
Find answer without queries(like in subtask 3). Because all operations change two adjacent values only
for these values borders will change. We can find new borders with data structure, for example, segment
tree. O(nlogn)
6. n ≤ 105 , q = 0.
We will calculate the number of edges in Sl,r . Edge will in Sl,r if in both components separated with this
edge have at least one vertex from the interval. We will calculate the number of intervals that don’t. Fix
any root. Keep set for every vertex that contains all vertex from subtree. Calculate the number of the
interval that fully in or fully not in set. To calculate this set for vertex calculate it for child vertexes, merge
them(Small to Large), and add this vertex. We can keep this set using segment tree or std::set.O(nlog 2 n)
7. Original problem constraints.
Like in subtask 5 only for ends of edges answer will change. Do all like in subtask 6 but persistently.
O(nlog 2 n)
Page 4 of 4