Hello, everyone!
Japanese Olympiad in Informatics (JOI) Final Stage 2026 (Contest URL) will be held from March 21st to 24th. There are 4 days in the contest. Note that the Final Stage is a kind of IOI selection camp, which is equivalent to Spring Training in 2025 or before.
- Day 1: March 21, 02:00 GMT — March 21, 24:00 GMT
- Day 2: March 22, 02:00 GMT — March 22, 24:00 GMT
- Day 3: March 23, 02:00 GMT — March 23, 24:00 GMT
- Day 4: March 24, 02:00 GMT — March 24, 24:00 GMT
The contest information is as follows. Details are available in contest page.
- Number of problems for each contest: 3-4 problems
- Style: IOI-Style (There may be some partial scores)
- Problem Statement: Japanese & English
- There may be some unusual task (e.g. output-only task, communication task) like IOI
The registration page and live scoreboard will be announced 10 minutes before the contest.
We welcome all participants. Good luck and have fun!
UPD1: The first contest will start in 8 hours.
UPD2: Contest Day 1 is started.
UPD3: Contest Day 1 is ended. You can discuss the problems.
UPD4: Contest Day 2 is started.
UPD5: Contest Day 2 is ended. You can discuss the problems.
UPD6: Contest Day 3 is started.
UPD7: Contest Day 3 is ended. You can discuss the problems.
UPD8: Contest Day 4 is started.
UPD9: Contest Day 4 is ended. You can discuss the problems. Thank you for participating in this event.








Is there an error in the scoreboard?
Thank you for letting us know! There was an error but it should have been fixed now.
When/where can the problems be discussed?
the problems are usually discussed under this blog itself, after the contest window ends for everyone (roughly 2 hours from now for day 1)
Where can we upsolve the problems ?
How to solve multi? I can't get anything better than $$$log_2{N}+2 = 10$$$
The goal is calculating MST weight of the complete graph. A natural first idea is to just run Boruvka until only one component remains: in each round, every vertex sends its cheapest edge leaving its current component, and from all those messages everyone can reconstruct one full Boruvka phase and the new contracted graph. But this requires $$$\lceil \log_2 N \rceil + 1$$$ rounds.
A 7-round solution:
Rounds 1 to 4: run Boruvka. In each round, every vertex sends its cheapest edge leaving its current component. From all N messages, everyone can reconstruct the whole Boruvka phase, contract components, and relabel them. After 4 phases, the number of components is at most $$$\lceil N/16 \rceil \le 16$$$.
Round 5: now work on the quotient graph of those remaining components. Since there are at most 16 components, there are at most $$$16 \choose 2$$$ $$$=120$$$ component-pairs. Assign one recipient to each pair $$$(a,b)$$$. Every vertex in component $$$a$$$ sends to that recipient its own cheapest edge into component $$$b$$$, so the recipient can take the minimum and recover the exact edge weight between components $$$a$$$ and $$$b$$$. (If $$$N \lt 120$$$, there are at most 8 components so it works; it works in the same way for smaller $$$N$$$)
I don't have 6-round solution; wonder how to do it (94 points seems possible in similar approach)
hint: $$$1 \to 3 \to 6 \to 12 \to$$$ contract components
Does anyone know the intended time complexity for subtask 4 ($$$n \lt = 5000$$$) of day 1 problem 2 (garden)? I have a $$$O(n^2log(n))$$$ solution that TLE's on it.
Does anyone want to explain their approach to dangos and gardens?
Let us discuss a bruteforce solution. Multiply $$$A_i$$$ by $$$-1$$$ for even indices.
Start with $$$S = ans = 0$$$. Then for $$$i = L$$$ to $$$R$$$, do the following updates
Now, the optimization. Note that if the step $$$S = \max(S, 0)$$$ never happened, i.e. $$$S \ge 0$$$ always, then the answer is simply $$$\dfrac{A_L + \ldots + A_R}{K}$$$.
For each index $$$i$$$, suppose we found the first index $$$j$$$ such that $$$S = \max(S, 0)$$$ takes place first time at $$$j$$$ if we start from $$$i$$$. Then, we can answer all the queries using binary lifting (the contribution to answer from $$$i$$$ to $$$j$$$ can be found with previous observation).
The condition for $$$j$$$ to be first zero-ing index after $$$i$$$ can be written as $$$(A_i + \ldots + A_{j - 1}) \mod K + A_j \lt 0$$$, or equivalent $$$(P_{j - 1} - P_{i - 1}) \mod + A_j \lt 0$$$, where $$$P$$$ is a prefix sum array.
If $$$A_i \le -K$$$, it is always acting as a bad-index, and otherwise for $$$-K \le A_i \lt 0$$$, it is a bad index for (one or two) subarrays of values (taken modulo $$$K$$$). We can maintain a segment tree modulo $$$K$$$, where each node represents the minimum bad index for that modulo class.
The final complexity becomes $$$O(N \cdot log(N))$$$ after coordinate compression.
Let us try to find $$$R_i = $$$ maximum row of an off limit cell after the first $$$i$$$ days. If we symmetrically find the minimum row, maximum and min columns, we are done.
The core idea is to maintain an incremental pointer.
Note that this works because of two reasons — firstly, updates only create new off-limit cells, never remove previous ones; and secondly, we only care about the maximum bad row at each time and not some other problem (for example, solving time the $$$i$$$-th row went bad seems hard).
You can maintain a lazy add, max finder segment tree to handle the updates. The final complexity is $$$O(N \cdot log(N))$$$
in dagnos
how to found the first index j such that S=max(S,0) takes place first time at j if we start from i for each index i??
can you send code solution for dagnos?
How to solve casino and teleporter?
First, note that exactly one cell in each diagonal will be modified, and we want to transmit $$$64 - 15 + 2 = 51$$$ cells (-15 represents one corrupted cell in each diagonal, +2 because $$$(0, 0)$$$ and $$$(7, 7)$$$ can always be recovered). Now, consider the second diagonal, which has two cells. We can encode "A" in this diagonal as "AA", and "B" in this diagonal as "AB". Then, if we receive "AB" or "BA", we know two things:
Similar logic applies to the case in which we receive either "AA" or "BB".
Now, how can we generalize this? Assume we are at the $$$i$$$th diagonal, and we also know that the adversary was at position $$$x$$$ in the $$$i - 1$$$th diagonal. Then, it will modify either $$$x$$$ or $$$x + 1$$$ in the $$$i$$$th diagonal, so we just have to be able to figure out which one it picks. Here's one way to do this: if we want to encode a string $$$s$$$ of length $$$l$$$ in a diagonal of length $$$l + 1$$$, set the first $$$l$$$ bits of that diagonal to $$$s$$$. Then, set the last bit such that there are an even number of As that lie on even indices in this diagonal. For instance, if we want to encode $$$s = ABAB$$$, we should set the diagonal to $$$ABABB$$$ (here, we 0-index, so the even indices correspond to [A, A, B]).
Then, after the adversary modifies this diagonal, we can check the parity of the number of As on even indices. If this parity remains even, the adversary modified an odd index; otherwise, the adversary modified an even index. Since exactly one of $$$x$$$ and $$$x + 1$$$ is even, and exactly one is odd, we can then determine precisely which one was changed and therefore recover the entire diagonal.
Thank you for your reply! I know the solution now.
Do you know how to solve JOI Tour?
I only know how to solve Subtask 1~8, don't know how to solve the whole problem.
What was your solution(s) for subtasks 1 — 8?
First consider a brute force for chain: $$$u = 1, 2, \dots, n$$$
(in this order!) for every path that contains $$$u$$$, for every other nodes $$$v$$$ lie on the path, let $$$c_{a_v} \leftarrow c_{a_v} + 1$$$, then for $$$k = 1, 2, \dots, q$$$, let $$$ans_i \leftarrow c_{b_k - a_u}$$$, and the complexity is $$$O(nm + nQ)$$$, this can pass Subtask 2,6,8.
We can split into $$$\sqrt{n}$$$ blocks and change the update-query complexity to $$$O(\sqrt{n})-O(\sqrt{n})$$$ and can pass $$$Q = 1$$$.
For tree, we can use euler order to reduce the problem to chain.
In the case of a tree structure, is your Euler sequence something like $$$(v_1, +1), (v_2, +1), (v_2, -1), (v_3, +1), (v_3, -1), (v_1, -1)$$$...?
I ask this because, during the contest and now, I haven't been able to find a way to represent a path with just a single interval. Does each path consist of a combination of two intervals, such as $$$[tin[lca], tin[s]]$$$ and $$$[tin[next(lca)], tin[t]]$$$?
For the path $$$u,v(in_u \lt in_v)$$$, if $$$u$$$ is not an ancestor of $$$v$$$ and we use our unchanged euler sequence, $$$u \to u'$$$ will have a coefficent of $$$-1$$$ and $$$v \to v'$$$ will be $$$1$$$, then we multiply $$$[out_u,out_{u'}]$$$ by $$$-1$$$ can fix this issue.
$$$u'$$$ is the second vertex from $$$\text{lca}(u,v)\to u$$$, same for $$$v'$$$. There is still only $$$O(1)$$$ ranges.
for the final subtasks, i believe a well-implemented $$$O(n (mq)^{0.5})$$$ passes (I implemented that for the line case)
How to solve JOI-Tour in such complexity?
For chain scenario, decompose the chain into blocks of length $$$\sqrt n$$$, for each whole block in a path, it can be paired with elements in $$$O(1)$$$ intervals in this path, and you calculate this for each block separately, in $$$O(nq+m\sqrt n+n\sqrt n)$$$ time. For partial blocks, we need to calculate ways to pair element using one from $$$[l_1,r_1]$$$ and $$$[l_2,r_2]$$$ each, and the length of the intervals are $$$O(\sqrt n)$$$, so you do sweep line and brute force add all elements in $$$[l_2,r_2]$$$ at time $$$l_1$$$ and exclude them at time $$$r_1+1$$$, also in $$$O(m\sqrt n+nq)$$$ time.
Tree scenario is just chain + euler tour.
If we have removed some teleporters, consider how to find the maximum number of warp travels in Bitaro's route. Bitaro starts at $$$1$$$. When Bitaro is at position $$$x$$$, he greedily chooses a teleporter $$$s\to t$$$ that satisfies $$$s\ge x$$$ and has the smallest $$$t$$$.
Consider dynamic programming. Let $$$f_{i,j}$$$ denote the minimum cost required to move Bitaro to point $$$i$$$ in exactly $$$j$$$ steps. The cost of a transition $$$f_{i,j}\to f_{k,j+1}$$$ is the sum of the costs of teleporters satisfying $$$i\le s \lt t \le k-1$$$ (these teleporters must be removed to allow Bitaro to reach $$$k$$$). If we add an artificial point $$$n+1$$$, then $$$f_{n+1,K+1}$$$ gives the answer.
When $$$K$$$ increases, the answer decreases monotonically. Hence we can apply the Aliens trick (WQS binary search) to remove the constraint on $$$K$$$. We then define $$$f_i$$$ as the minimum cost to reach point $$$i$$$, and the transition cost from $$$f_i$$$ to $$$f_k$$$ is the sum of the costs of teleporters with $$$i\le s \lt t\le k-1$$$, plus a constant penalty. This DP can be computed in $$$\mathcal O(n\log n)$$$ using a segment tree.
The overall time complexity is $$$\mathcal O(n\log n\log V)$$$.
During the contest, I noticed that the transition cost satisfies the quadrangle inequality, so I tried using a simplified LARSCH algorithm to compute each round in $$$\mathcal O(n\log^2 n)$$$ with a persistent segment tree. However, this led to TLE, so I switched to running the DP directly with a persistent segment tree, which improved the complexity to $$$\mathcal O(n\log n)$$$.
Thank you for your solution!
Thanks for the detailed explanation!
1. Yes, it was a typo. Fixed.
2. The problem can be seen as partitioning the interval $$$[1,n]$$$ into $$$K+1$$$ segments (e.g., $$$[1,10] \to [1,3], [4,5], [6,10]$$$). The cost of a segment $$$[l,r]$$$ is the sum of the costs of teleporters that satisfy $$$l \le s_i \lt t_i \le r$$$; we denote this cost by $$$w(l,r)$$$.
$$$w(l,r)$$$ satisfies the quadrangle inequality: for any $$$1 \le a \le b \le c \le d \le n$$$, $$$w(a,c)+w(b,d) \le w(a,d)+w(b,c).$$$ This can be proved easily by drawing intervals on a Cartesian plane where the $$$x$$$-axis and $$$y$$$-axis represent the left and right endpoints respectively. The intervals lying in the rectangle $$$[a,b-1] \times [c+1,d]$$$ are counted in $$$w(a,d)+w(b,c)$$$ but not in $$$w(a,c)+w(b,d)$$$.
Because $$$w$$$ satisfies the quadrangle inequality, the answer is convex in $$$K$$$. For a detailed proof, see this link.
3. The DP transition is $$$f_i = \min_{j \lt i} \big( f_j + w(j, i-1) \big)$$$. We sweep $$$i$$$ from $$$1$$$ to $$$n$$$ and maintain $$$f_j + w(j, i-1)$$$ for all $$$j$$$ using a segment tree.
When we process $$$i$$$, all teleporters with $$$t \lt i$$$ have already been added to the segment tree. Thus we can query the minimum value of $$$f_j + w(j, i-1)$$$ and also retrieve the smallest $$$j$$$ that achieves this minimum.
After computing $$$f_i$$$, we add the teleporters with $$$t = i$$$ to the segment tree. For a teleporter $$$(s, i, \text{cost})$$$, it increases $$$f_j + w(j, i-1)$$$ by
costfor every $$$j \le s$$$ (because these $$$j$$$ now have one more teleporter inside the interval $$$[j, i]$$$).That makes sense, thanks!
Is there a different way to solve teleporter than using DP + aliens trick?
Why https://cms.ioi-jp.org/ Display 502 Bad Gateway?
There's no problem now,
Could anyone share their solutions for Day 3?
Sorry, I don't really feel like describing Rainfall right now.
Consider the $$$1$$$-dimensional problem. Covering each point by $$$K$$$ is equivalent to choosing a regular bracketed sequence of length $$$2 \cdot K$$$ where $$$x \ge X_i$$$ are open brackets, and $$$x \le X_i$$$ are closing brackets.
Now, there are a few ways to solve it. I used Alien's trick. For each pair of brackets matched, make the cost $$$C_i + C_j - L$$$ instead of $$$C_i + C_j$$$ for some parameter $$$L$$$, and then binary search on the optimal $$$L$$$ to have exactly $$$K$$$ matches (including $$$X$$$ and $$$Y$$$ dimensions).
You can solve the above problem with regret greedy. For every opening bracket, insert $$$(C_i - L)$$$ into a set. For every closing bracket, take out the optimal choice from the set and use it if it reduces total cost. Also, insert back $$$(-C_j)$$$ if you are using (to maybe overturn the decision later, regret greedy style).
The final complexity here becomes $$$O(N \cdot log(N) \cdot log(A))$$$
This is a standard centroid decomposition task. Split over the centroid, and then count for each $$$u$$$, how many valid $$$v$$$ exist.
Either the path $$$u \rightarrow root$$$ is good (i.e. we can stamp something on this path), in which case $$$v$$$ just needs to satisfy $$$d(u, v) \le D$$$ and $$$(u, v)$$$ in different subtrees. This is a well known task, and can be done with the observation that each $$$v$$$ induces a prefix of depths of $$$u$$$ to be good.
When $$$u \rightarrow root$$$ is not good, we need $$$root \rightarrow v$$$ to be good. For that case, it is easy to see that let $$$M = \min(a_i - dep_i)$$$ on this path, we must reach $$$root$$$ at time $$$\ge M$$$ only. So, in this case, each $$$v$$$ induces a subarray of depths of $$$u$$$, instead of a prefix.
We can maintain this info in a segment/fenwick tree to get $$$O(N \cdot log^2(N))$$$
How did you get the centroid to pass the time limit? I only managed to get 72 with this approach.
Fenwick trees are pretty fast, also you can optimize to $$$O(N \cdot log(N))$$$ too, its just slightly annoying (use difference arrays instead of fenwick trees, all all updates before all queries, but this doesn't enforce $$$u$$$ and $$$v$$$ different subtrees so subtract out same subtree)
would that require $$$O(D)$$$ computations at each centroid?
O(max depth) which is O(size), and similarly for each subtree of child of centroid, its O(subtree size) adding to O(size)
It's quite easy to optimize to $$$O(n\log n)$$$ with prefix sum.
This is a solution idea for Voltage, could someone verify that it's correct?
EDIT: Seems to be correct, I just got AC with this.
If a cycle exists, we can't figure out the direction it goes in. This is because any assignment that traverses like $$$a \to b \to c \to a$$$ would give the same answer on $$$c \to b \to a \to c$$$. So our graph is a DAG.
Define a 'sink' to be a node with an outdegree of $$$0$$$. Then we maintain a set of already processed sinks. To find a new sink, we notice that querying $$$v$$$ active with sinks active vs just sinks active gives us $$$0$$$ iff $$$v$$$ is a sink.
Once we find $$$v$$$, we wish to find $$$u\to v$$$. For this, fix a set $$$S$$$, then we compare sinks + $$$S$$$ with sinks + $$$v$$$ + $$$S$$$. If the former is greater, we know that at least one node from $$$S$$$ has an edge to $$$v$$$.
In $$$O(\log{n} \cdot \deg(v))$$$ time, we can find all such $$$u$$$ (split into two sets and recurse). We repeat till we exhaust all nodes or we cannot find a sink anymore (which means there's a cycle, and we cannot determine the graph).
Finding sinks in total takes $$$O(n+m)$$$ queries (if we realise that the only new sinks that can be formed are ones that were just identified as $$$u$$$'s) so this should be good enough.
You can do the same just starting from inDegree=0 nodes and move toposort style.
How do we solve Baker? I can't think of anything better than range queries on a merge-sort tree of convex hulls which would give $$$O(\log^2(m))$$$ or something per query, which is probably too slow to AC.
By sorting queries, they take amortized $$$O(1)$$$ per node, which is $$$O(\log m)$$$ amortized per query.
Holy crap yeah, that's incredibly straightforward! Thank you.
Could you please give me more information?
I tried this: Each query only had one prefix, and it was always best to take a suffix of that prefix so we could do a binary search. We could take $$$x$$$ to $$$y$$$ if $$$B+(i-x+1)A \le T_i+L$$$ when I rearranged the equation, $$$T_i+(i+1)A \le Ax-B+L$$$. The left side could be calculated with a convex hull, and the right side is $$$O(1)$$$. Then I could get 60 points with $$$O(log^2 m)$$$, which means $$$T_M \le B$$$. I tried something like merge-sort tree on convex hulls and sorting the queries, but it was also $$$O(m log^2 m)$$$ and it didn't do any subtasks except the first and second.
For each node in the merge-sort tree, we build a monotonic CHT. We partition each $$$[l,r]$$$ into $$$O(\log(m))$$$ many ranges, and maintain a vector of all the queries associated with each segment tree (or merge-sort tree) node. This allows us to answer all queries for a given node in amortized $$$O(1)$$$ time. While building up, we also run merge sort to sort the lines.
It is not necessary to sort $$$\text{seg}[v]$$$ for each query, we can pre-sort all queries according to their $$$a$$$ value, so the complexity should be $$$O((m+q) \log(m))$$$.
Although, even I TLE everything except the first two subtasks with this approach.
EDIT: I managed to get 82 points (so the 22 point subtask) by using
long doubleinstead of__int128_tEDIT 2: Got AC! Turns out I didn't even need the merge sort because lines were already sorted by slope :facepalm:
I'm not sure if I understand how you answer queries when you have a bunch of lines
If your queries are monotonic: so something like $$$x, x+1, x+2$$$ or even $$$x, x-1, x-2$$$, we can answer queries while popping lines (which are sorted by slope themselves) from the front/back and don't need to perform a binary search to find the best line. Instead, we simply evaluate the last/first (depending on how queries are sorted) line against the line before that, and if the other line before does better, we pop the last line.
I also cant get the last subtask even when my code is (m+q)logm :(
My code runs in 0,7 seconds in the 22 point subtask how fast is yours?
I got 100 now when I changed my segtree size to m*2 from m*4! You should try it if you also use one with size m*4
Thanks for the problems. Some of them felt pretty annoying especially Rainfall and Festival, but I enjoyed the contests as whole.
I made all my implementations (except JOI Tour, i am yet to solve that) public on Github
It's interesting to see that for Baker, when I use global arrays for queries and lines, I get TLE, but when I change it to divide and conquer, like your code, which returns vectors and takes references, I get AC in less than 1.5 seconds.
after several hours of coding and debugging, i was able to pass JOI Tour too, and i have added that to the repository. It is $$$O(M \sqrt{N} + NQ)$$$ following Kevin114514 comment