0% found this document useful (0 votes)
35 views

Tutorial

Uploaded by

Arthur Lobo
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
35 views

Tutorial

Uploaded by

Arthur Lobo
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 6

44th Petrozavodsk Programming Camp, Winter 2023

Day 4: KAIST+KOI Contest, Grand Prix of Korea, March 12, 2023

Problem Tutorial: “Ring Road”


Let’s start by transforming the input instance to a binary tree: For any node with degree greater than 3,
you can introduce additional edges with weight 0 to make a binary tree with equivalent distances. The
nodes are doubled, but it doesn’t matter because TL is lenient.
Construct a centroid decomposition per the given binary tree. Let c be the centroid of current subproblem.
Since c has at most 3 child, we have 3 subtrees as well.
The optimal path always takes the following form:

• It passes a centroid c.

• It does not pass a centroid c but uses some edges that connect different subtrees of c.

• None of the above.

The first case can be solved easily by computing a single-source shortest path from c, using Dijkstra’s
algorithm.
For the second case, the edges that connect different subtrees of c are ring roads, and you can observe
that they are at most the number of c’s children. This fact is obviously true for the original tree. For
the subproblems, note that you can add at most one edge that the graph is still a tree where each leaf
is augmented with ring roads. Therefore, there are at most 3 edges that connect different subtrees of c.
Passing an edge means passing one endpoint of each edge, so you can compute 3 single-source shortest
path from any arbitrary endpoint of such edges.
The third case only holds if the queried vertices belong to the same subproblem - proceed recursively.
Each queries belong to at most O(log N ) subproblems, and for each layer you call Dijkstra’s algorithm 4
times, which takes O(N log N ) time. As a result, we obtain an O(N log2 N + Q log N )-time algorithm.
To find the relevant ring roads in the second case, simple DFS is sufficient, and you don’t need any analysis
of the specific structure of the given graph.

Problem Tutorial: “Query on a Tree”


The quantity strength(S) is a sum of |S2i | where Si are the connected components of S under the given


tree. Naively, you can scan all tree edges where both endpoints belong to S and compute the components
with graph search or disjoint sets, which requires O(N ) time per query and times out.
Performing DFS on the vertices of S may seem to work, but this approach may encounter many irrelevant
edges, hence this also times out.
To improve the algorithm, root the tree arbitrarily, and compute the parent for all non-root vertices. An
edge is relevant if and only if par(v) ∈ S, v ∈ S, therefore you can simply
Piterate through S and check if
par(v) ∈ S with a simple boolean array. The time complexity is O(N + Ki ).

Problem Tutorial: “A+B Problem”


The graph is known as Halin graph, and the problem asks us to compute the tree decomposition. Tree
decomposition is a generalized way of characterizing graphs that are similar to trees (such as cacti). This
problem essentially asks to prove that Halin graphs are similar to trees (and hence many tree-specific
techniques just work). From now on we will use a standard vocabulary:

• New trees are called skeleton tree.

• Revolutionary sets are called bags.

• max |Xi | − 1 is called treewidth (We have to compute width-3 tree decomposition).

Page 1 of 6
44th Petrozavodsk Programming Camp, Winter 2023
Day 4: KAIST+KOI Contest, Grand Prix of Korea, March 12, 2023

Let’s assume that the input is a binary tree. If we ignore the ring road, we can construct a trivial
decomposition:

• Skeleton tree is just the input tree.


• Each bag contains the node, and the parent (if it is not a root).

It’s easy to verify that the decomposition is valid, and has width 1. The tree is binary, so supporting the
ring road is simple: For each ring road (u, v), add the element u over the path between u and v. This
modification yields a solution of width 4.
To reduce the width by one, we appropriately subdivide the edges of the skeleton tree and spread the
element of bags. Let df s(v) be the recursive function such that:

• it computes the tree decomposition of subtree of v.


• if (la , la+1 ), (lb , lb+1 ) are the ring road that goes out of the subtree in left/right direction, returns a
skeleton tree where the root node has bag (la , v, lb ).

For some child (w1 , w2 ) of v, the return value of df s(w1 ), df s(w2 ) will be (la , w1 , lb ), (lb , w2 , lc ), respectively.
We can merge them in a following way:

• Attach a new root node (la , w1 , v, lb ) for w1 (and similarly to w2 )


• Attach a new root node (la , v, lb ) for w1 (and similarly to w2 )
• Merge two trees with new root (la , lb , lc , v).
• Attach a new root node (la , v, lc ).

We need 4 new nodes for merging two trees, hence the construction yields a skeleton tree of size at most
4N . Generalizing this to a non-binary tree is trivial.
Remark. As noted, the tree decomposition of a graph makes tree-specific techniques applicable to general
graphs. For example, problem A can be solved by constructing a tree decomposition as in this problem,
and by applying your favorite way of computing distance in a tree (centroid decomposition or sparse
table). Of course, it’s much easier to use ad-hoc approaches to problem A, but author knows at least five
problems that can be described as "find tree decomposition, and copy-paste distance computing template
in bounded treewidth graph"(For example, NEERC 2015 C, GCJ 2020 R2D, JOI Spring Camp 2017
D2P3).

Problem Tutorial: “Building Bombing”


For buildings on the left to building L, we only have to blow up the buildings that block building L from
being visible. The main problem is to solve for the buildings on the right. From now on, we will assume
L = 1.
We can solve the problem using dynamic programming. Let D[i, k, h] be the minimum number of buildings
to blow up only considering buildings 1 . . . i, and after blowing up, the number of visible buildings becomes
k and the greatest height among them becomes h.
We will add buildings one by one and calculate the corresponding DP values. There are three cases to
consider when adding building i to the set. We can make it visible by taking k − 1 visible buildings on
the left, where the greatest height is less than hi . Or, we can make it invisible either by blowing it up or
hiding it behind another building. The recurrence relation is as follows.

for h < hi

D[i − 1, k, h] + 1

D[i, k, h] = min(DP [i − 1, k, h], minh0 <h D[i − 1, k − 1, h0 ]) for h = hi
for h > hi

D[i − 1, k, h]

Page 2 of 6
44th Petrozavodsk Programming Camp, Winter 2023
Day 4: KAIST+KOI Contest, Grand Prix of Korea, March 12, 2023

This takes O(N 2 K) naively, so we have to do it efficiently. Suppose we have added buildings 1 . . . i so far.
We will store K arrays D[i, k, ∗] for k = 1 . . . K in K segment trees. Now, the task of adding a building
to the set becomes adding 1 to a range, querying the minimum in a range, and updating a point in a
segment tree. Each task can be done in O(log N ) per segment tree using lazy propagation. Since there
are K segment trees and we will add N buildings in total, the time complexity is O(N K log N ).

Problem Tutorial: “Double-Colored Papers”


We build a suffix automaton for S and T , A and B. Then, all possible double-colored paper is a combination
of path in automaton of S starting from the root, and path in automaton of T starting from the root.
Our strategy is to fix the characters one by one: if we have found the prefix pf x of the answer string ans,
we can find the next character of ans, or conclude that pf x = ans if we can calculate the number of
double-colored papers with having pf x + c as prefix, where c is a arbitrary character.
To do this, we should analyze the possible pair of paths given the string pf x. Let u be the vertex in A
reached when following the path pf x until there is no edge of desired direction, and v be the vertex in B
reached when following the path pf x, following the link edge while there is no edge of desired direction.
All possible endpoints of the first path are the vertices in the path in A from root to u, and all possible
endpoints of the second path are the vertices in the path in link tree of B from root to v. The two pair of
vertices are a valid pair if sum of the lengths they present is |pf x|. Be careful that vertices in B correspond
may present multiple lengths.
Note that we are finding the maximum possible length of prefix and suffix of pf x that is included in S
and T by this procedure, and we can maintain u and v while adding characters to the end of pf x.
With dynamic programming in A and B, we can calculate the number of paths starting from each vertex
in the automaton, cnt.
To count the number of pair of paths, note that the vertices in B that are included in a valid pair forms
a suffix of the path: we can also store the first vertex not included in the suffix. Let’s call it w. Then, the
number of pair of paths is sum of cnt values multiplied by the number of lengths the vertex is representing,
for the vertices in the path w − v in the link tree of B. w and v should have extra care, as only some
suffix of w is counted and some prefix of v is counted, depending on minimum and maximum length of
possible suffix of pf x.
With dynamic programming in link tree of B, we can calculate this value after adding character c to the
end, in a method similar to prefix sum. If we update u, v and w after each update, we can solve the whole
problem in O(26(|S| + |T |)).

Problem Tutorial: “Making Number”


Let’s define Ni as the i-th digit of N .
There is two cases for Z:

• Z =Y.

• There exists an unique index i, Zj = Yj for 1 ≤ j ≤ i − 1 and Zi > Yi .

The first case is checked easily by comparing counts of each digit.


For the second case, we can find an answer by binary searching the index i.
Let’s define I(j) as the maximum index satisfies following, corresponding to a given index j:

• I(j) ≥ j

• Yk ≥ Yk+1 for j ≤ k ≤ I(j) − 1

Page 3 of 6
44th Petrozavodsk Programming Camp, Winter 2023
Day 4: KAIST+KOI Contest, Grand Prix of Korea, March 12, 2023

i.e. I(j) is the maximum index such that Nj∼I(j) is non-increasing sequence.
It can be checked that i ≤ j for given index j with following steps.

1. Calculate CI (d), the count of digit d in Yj∼I(j) , for 0 ≤ d ≤ 9.

2. Calculate CP (d), the count of digit d in Y1∼j−1 , for 0 ≤ d ≤ 9

3. Calculate CX (d), the count of digit d in X, for 0 ≤ d ≤ 9.

4. If CX (d) < CP (d) for some digit, result i < j.

5. Find the maximum digit d satisfies CP (d) 6= CX (d) − CI (d).

6. If there is no such d or CP (d) > CX (d) − CI (d), result i < j.

7. Otherwise, check the existance of d0 satisfies d0 < d and CP (d0 ) > 0.

8. If d0 exists, result i ≥ j. If not, result i < j.

Each step can be proceed in the node of segment tree where the node of segment tree is consists of count
of each digit in each interval, l to r and l to min{I(l), r}.
Time complexity is O(D(N + Q log N )) where D is the number of digits.

Problem Tutorial: “Permutation Arrangement”


Suppose that there are non-adjacent 8 empty spaces left in the permutation. Then, each remaining number
has at least 4 squares that it can go to and each remaining square has at least 4 numbers that can be in
the square. Hence, from Hall’s marriage theorem, there exist the valid arrangement of remaining numbers.
Hence, when there are 15 or more empty spaces it is always possible to arrange the remaining numbers.
Therefore, the solution of greedily assigning numbers until there are 15 numbers left and using bit DP to
find the optimal assignment of last 15 numbers works.
From case-work it is possible to bring the minimum number of empty spaces needed down and hence the
brute force solution of testing all the permutations in lexicographical order also works when implemented
well.
The time complexity is O(N ).

Problem Tutorial: “Squirrel Game”


Let di be the sequence of distances between the squirrels. That is, di = xi − xi−1 − 1, assuming there
also is a squirrel at x0 = 0. A single move decreases di by some amount and increases di+K by the same
amount for some i. (If di+K does not exist, we just ignore it.) We can decompose the game into K distinct
chains of distances in the form dKq+r , for each r in 0 . . . K − 1. Each chain is equivalent to a game where
K = 1. If we can calculate the Grundy number of each chain, we can solve the entire game using the
Sprague-Grundy theorem. However, it turns out that we don’t even need the Sprague-Grundy theorem
to solve this problem.
Let us first solve for K = 1. From the right, label the squirrels with R and L alternatingly. We can pair
up two consecutive squirrels with the label L on the left and R on the right. We claim that the game is
equivalent to a Nim game where the heap sizes are the distances between each squirrel pair.
Suppose you have a winning strategy and have played accordingly. Your opponent has two choices: Move
a squirrel labeled L or labeled R. If your opponent moves a squirrel labeled R, it is equivalent to reducing
the heap size in the corresponding Nim game. Therefore, you are still in a winning position. If your
opponent moves a squirrel labeled L, which is increasing the heap size, you can move the paired squirrel
of label R so that the heap returns to the original size. Therefore, you are back in the winning position.

Page 4 of 6
44th Petrozavodsk Programming Camp, Winter 2023
Day 4: KAIST+KOI Contest, Grand Prix of Korea, March 12, 2023

Note that the game has to end in finite turns because each move reduces the sum of xi . It means that
your opponent cannot indefinitely stall the game by always increasing the heap size.
When K > 1, the game is equivalent to playing K distinct Nim games, which is just a single Nim game
with all the heaps from each game.

Problem Tutorial: “Two Paths”


First, with dynamic programming, we can find the result of following query F (u, v, w) in O(1): the farthest
vertex from u except for the directions v and w, where v and w are either vertex connected to u or 0(no
direction).
For a single query, let P be the path from u to v. Let w1 be the last vertex of P1 inside P , and w2 be the
last vertex of P2 inside P . If we fix some vertex c inside P , then we can divide the cases by three: both
w1 and w2 is in c - u path, both w1 and w2 are in c - v path, or w1 is in c - u path and w2 is in c - v path.
With centroid decomposition, we make c be the root of the tree. Note that while P is inside the current
tree, now P1 and P2 may not be fully included in the tree, so we use F query to find the actual farthest
vertex in the tree.
First, let’s solve the case where w1 or w2 is c, and the case where w1 is in c - u path and w2 is in c -
v path. In this case, optimal choice of w1 and w2 is independent, so by calculating optimal w for each
vertex using dynamic programming(Using the F query), this case can be solved in O(1).
Now we solve the case where both w1 and w2 is in c - u path. The case where both w1 and w2 is in c - v
path can be solved symmetrically. In this case, if w1 is fixed, the optimal w2 is fixed, and can be found
by dynamic programming(Again using the F query). Also, the result value with w1 and w2 fixed can be
expressed as a line Ax + By + C for A, B values in each query, and C being a constant fixed for each
query. Therefore, we can solve this case with Convex Hull Trick in tree. You should be careful with the
case u = w1 .
The time complexity is O(N log2 N + Q log N ).

Problem Tutorial: “Village Planning”


(N )
K = 0 is easy: answer is A0 2 for each N .
K = 3 is a trick: the answers are equal with the case K = 2.
Now we only need to solve K = 1 and K = 2. First, we solve the case where Ai = 1 for all i: we just need
to count the number of possible graphs.
For both K = 1 and K = 2, we first count the number of possible connected components for each size,
ci . Then, we can count the number of ways to merge the components.
Let’s fix the P
number of components k, and label each component from 1 to k. Let Qk size of component i
be ni , where ki=1 ni = N . Then, the number of possible ways would be n1 N i=1 cni . Therefore, the
 Qk···nk
N
number of graphs with k connected components is n1 +···+nk =N n1 ···nk i=1 cni . Finally, to remove the
P
order of the components, we divide the result by k!.
The above analysis tells us that if the exponential generating function of c is P (x), then answer’s
P (x)k
exponential generating function is ∞
P
k=0 k! = exp(P (x)).
When K = 1, each connected component is a tree. The number of connected components of size N is
N N −2 .
When K = 2, each connected component is a tree or a unicyclic graph. Let’s count the number of
connected unicyclic graph of size N .
The unicyclic graph is formed by a cycle and a rooted trees with each vertex in the cycle
being a root. Let Q(x) be the exponential generating function of N N −1 . By a similar analysis
to above, we can find the exponential generating function of the number of unicyclic graphs as

Page 5 of 6
44th Petrozavodsk Programming Camp, Winter 2023
Day 4: KAIST+KOI Contest, Grand Prix of Korea, March 12, 2023

P∞ Q(x)k (k−1)! P∞ Q(x)k Q(x)2


k=3 k! × 2 = k=3 2k = 12 (− ln(1 − Q(x)) − Q(x) − 2 ).
Now, the general case where 1 ≤ Ai < 998244353 is not too different: for each step, we are merging
components. Note that the number of simple paths with both vertices in the same component is fixed,
and the number of simple paths with two vertices in different components is fixed. Using this fact, you
(N ) −(N )
can just modify the generating function before and after each step by multiplying Ai 2 and Ai 2 in
each terms appropriately.

Problem Tutorial: “Window Arrangement”


This problem can be modeled as MCMF as following.

1. Create one source vertex, one sink vertex, one vertex for each room, and one vertex for each places
where we can put windows

2. Make edges connecting source vertex and rooms and give it capacity according to number of windows
needed and cost zero.

3. Make edges connecting rooms and potential window locations. Give the edge capacity one and cost
zero.

4. For each potential window location, connect it and the sink vertex twice. The first edge has capacity
one and cost zero and the second one has capacity one and cost equal to the discomfort we get when
we put two windows in this location (i.e. product of numbers of people in two rooms connected to
this window location)

And now running MCMF algorithm on this graph solves the problem. The time complexity is O(n2 m2 ).

Page 6 of 6

You might also like