We are excited to announce that the Baltic Olympiad in Informatics (BOI) 2025 will take place this week in Toruń, Poland.
The official contest will be held:
- Dates: Saturday, April 26 and Sunday, April 27
- Time: 09:00 — 14:00 (Central European Summer Time, UTC+2)
- Live scoreboard: ranking.boi25.pl*
The public mirror contest will be held:
- Dates: Saturday, April 26 and Sunday, April 27
- Time: 10:00 — 15:00 (Central European Summer Time, UTC+2)
- Contest link: mirror.boi25.pl (available starting Friday, April 25th)
- Registration for the mirror contest will be available starting Friday, April 25 at 10:00 (CEST, UTC+2).
- A practice session will be held on Friday, April 25, from 16:30 to 23:59 (CEST, UTC+2).
Technical details:
- Format: IOI-style problems and scoring system.
- Available languages: C++ and Python.
- For all technical details, see the official website at boi25.pl.
- The problem statements will be provided in English and national languages of the participating countries.**
Stay tuned for updates and good luck in the contest!
— BOI 2025 Organising Team
* The scoreboard will be turned on after the mirror contest starts (after 10:00).
** Assuming delegations choose to translate them. If your country participates in BOI and you are interested in problems statements in your national language, please check with your BOI delegation.
Update: The second day of the contest starts in 3 hours (at 10:00, CEST, UTC+2 time).









Can we do the mirror (day 1) as a virtual contest later (after 26 april 15:00)
Will it be available on the CSES website right after the mirror ends?
We won't organise it, but we will share problem data after the contest ends.
will we have it on codeforces gym after it ends?
I don't think Baltic was over posted on CF, but probably it will be on qoj.ac
???
Ok I don't think Baltic always gets posted on CF
Will there be an editorial?
How to solve B?
I had this idea:
Create a new graph initally with M nodes. For each node track for every ingoing edge, the distint colors.
Now for each node and each color entering it create 3 nodes. We will call these nodes (u, c, 0), (u, c, 1) and (u, c, 2).
Now for an edge u -> v with color c and index id, add egde id -> (v, c, 0).
For every (u, c, 0) add edges to (u, c, 1) and (u, c, 2).
For every (u, c, 1) add edge to (u, prev(c), 1) and from every (u, c, 2) edge to (u, next(c), 2).
And add edge from (u, c, 1) to id and (u, c, 2) to id.
I suppose that every valid path in this graph will be valid in the initial, but I couldnt implement this in time.
Where can we find tasks?
The website doesn't load for me fsr
That is correct. You should be careful with the implementation though, because we are dealing with a graph that has 3 million vertices and 5 million edges.
The editorial and tests are available here: https://boi2025.mat.umk.pl/editorial_and_tests.php
You can also find the statements here: https://boi2025.mat.umk.pl/task_statements.php
Will the queue be fixed for Day 2?
no, cause submissions from the official contest have higher priority queue from the mirror contest.
We will have dedicated judges for the mirror for day 2 which should solve this problem. We apologise for the long queue on the first day.
Can someone help me understand why this solution for Gingerbread works?
I kinda coded this as a joke and submitted it just for fun. It somehow got 100?
In such number theory problems almost everything passes lol. I have a solution using DP which minimizes GCD given the number of operations. I have no idea why it's optimal to minimize GCD at each step. Also this solution didn't get 100 at first. Then I added
if (1.0 * clock() / CLOCKS_PER_SEC >= TL)and it passed.Not sure what you are doing here, but here is some reasoning for why most reasonable solutions will get AC on the problem:
The answer for two given $$$a, b \leq 10^{7}$$$ is apparently always $$$\leq 4$$$ (in particular, the answer is always $$$\leq 4$$$), so for $$$n \leq 8$$$, say, one can bruteforce the up to $$$4^{8}$$$ possibilities and win. If your code does anything like this, it solves the answer for small $$$n$$$. By the way, note that we may also expect bruteforcing $$$4^{8}$$$ to take care of automatically a random testcase where the answer is $$$ \gt 4$$$, since these pairs are very rare and it is highly unlikely that $$$(a, b)$$$ and $$$(a+1, b)$$$ are both rare.
For larger $$$n$$$, say $$$n \geq 9$$$ with some simple arguments it can be shown that the answer is always $$$0$$$ or $$$1$$$, since the $$$9$$$th primorial exceeds $$$10^{7}$$$. As a result, any bruteforce that is optimised in the sense that it stops searching for suboptimal answers relative to an already found answer will always succeed quickly for $$$n \geq 9$$$, since it would have already found a working example with $$$\text{cost} = 1$$$.
By the way, in case heuristics are unable to convince you the answer is low, I recommend looking at USA TSTST 2011/3, which proves that for two numbers $$$a, b \leq N$$$ we need no more than $$$O(\log N)$$$ steps to convert their $$$\gcd$$$ to $$$1$$$. Of course, this bound is very crude and in practice the answer is even lower.
Amazing, thank you so much. Legit crazy that this just worked lmfao
Edit: as to what I'm doing: I'm literally just brute forcing every way to distribute $$$i$$$ items across the $$$n$$$ elements of the array. There are:
$$$\displaystyle \binom{i+n-1}{n-1}$$$
ways to do this. If the $$$\gcd$$$ of the array becomes $$$1$$$ for any distribution, I just print $$$i$$$ and return immediately.
If this didn't make sense please feel free to ask for clarification!
How to do A and B? Is A similar to the slope trick
No. Problem A seems that you can write the brutest dp and optimize it by only recording the useful values of each $$$a'_i$$$. That is (for me), $$$a'_i$$$ is always in $$$a_{i\pm 0\sim 2}\pm 0\sim 4$$$ (maybe that's a very loose bound). Anyway, time complexity is absolutely $$$O(n)$$$.
EDIT. The solution turned out to be wrong.
Let's consider how big can be the answer for each query. Let $$$M$$$ be the maximum value in the segment $$$[L; R]$$$. Then I claim that:
1) The answer is at least $$$M$$$. Clearly, no matter what we do the answer is at least the maximum value in the segment.
2) The answer is at most $$$M + \lceil \log_2(R - L + 1) \rceil$$$. This bound is a less trivial one but can be achieved by doing operations in a (perfect binary tree)-like manner.
Also the subtask $$$A_i \le 20$$$ can be useful. Let $$$dp_{mx, i}$$$ be the maximum $$$j$$$ so that the answer for the range $$$[i; j)$$$ is at most $$$mx$$$. Then let's consider the cases to do the transitions:
1) $$$mx \lt A_i$$$. We can't take anything so $$$dp_{mx, i} = i$$$.
2) $$$mx = A_i$$$. Obviously, the best we can do is to take this element as a subsegment so $$$dp_{mx, i} = i + 1$$$ in this case.
3) $$$mx \gt A_i$$$. This case is more interesting. Let's consider the last operation that happened in the range $$$[i; dp_{mx, i})$$$. It's easy to see that we should merge $$$mx - 1$$$ with $$$mx - 1$$$ because otherwise we could extend the segment. So $$$dp_{mx, i} = dp_{mx - 1, dp_{mx - 1, i}}$$$ (like in binary lifting!).
To answer a query $$$[L; R]$$$ we find the minimum $$$x$$$ such that $$$dp_{x, L} \ge R$$$.
To get the perfect score firstly fix the maximum in each segment (that is, iterate over all the numbers $$$M$$$ in range $$$[1; 10^6]$$$ and consider all the queries where $$$M$$$ is the maximum number). Then let's observe that we don't actually need to care about the numbers less than $$$M - 2 \cdot \lfloor \log_2(N) \rfloor$$$ (that is, we can consider a whole block of such numbers as a single $$$-\infty$$$) -> WRONG!. Then we do the DP from the subtask $$$A_i \le 20$$$ for the numbers in the range $$$[M - 2 \cdot \lfloor \log_2(n) \rfloor; M]$$$ by compressing the values. The time complexity is $$$\mathcal{O}(N \cdot \log^2 N)$$$ because we will consider each $$$A_i$$$ at most $$$2 \cdot \lceil \log_2(N) \rceil$$$ times and doing the DP adds extra log (+ there are blocks of $$$-\infty$$$ but there are no more of them than half of the elements). Implementation:
The hack is
1 1 1 2 3 4 ... N 1 1 2 3 4 ... N(thanks Milmon for this test and avighnakc for letting me know about it).In your solution you say we don't need to care about numbers that are less than $$$M - 2 \log_{2}(n)$$$. I'm assuming this is probably because they can't get big enough to have a significant difference on the answer (given that they can increase by $$$\log_2{n}$$$ at most). But why is this bound not something like $$$M - \log_2{n} - 1$$$ instead?
I think the actual bound doesn't have this factor of 2 but my reasoning was like this: small numbers don't change much but having them in the middle might influence some bigger numbers (because we will eventually need to merge small elements with big elements), so we want to merge them into a single small number. So how much does it cost? The easiest way is to build an (almost) perfect binary tree on them. By doing it we increase the numbers by at most log, but if the number becomes greater than M — log it's no longer safe to assume that it won't become the maximum element. For example, if we have two big numbers, one was initially big and one became big enough after some operations why can't the latter one become the maximum if we do the operations treating this number as -infinity? Not obvious to me.
Also, I thought of another strategy that seems promising. Do you think it's optimal?
Solve with divide and conquer. At each level, choose the median occurence of the max element $$$M$$$, let that occur at index $$$k$$$. Then merge the left subtree $$$[1\dots k-1]$$$ and the right subtree $$$[k+1\dots n]$$$ recursively. Then if merging left with middle then right gives you a smaller value, do that, otherwise merge right with middle and then with left.
I'll have to think about how queries are handled and I don't have a formal proof for this being correct either, but I'd still like to know whether it is or not.
Also, sidenote: your solution assumes the following greedy algorithm is correct (which it is, but again, I don't have a proof for it): to get the smallest optimal value, merge $$$i$$$ with $$$i+1$$$ such that $$$\max(a[i], a[i+1]) + 1$$$ is minimized across all choices of $$$i \in [1, n)$$$.
Apparently a new hack makes this solution fail: https://qoj.ac/submission/1079924
Although I'm not sure what the exact hack is yet, I'm still trying to figure that out
https://boi2025.mat.umk.pl/editorial_and_tests.php
Hi, I don't know if it's just me but this link doesn't seem to be working.
Edit: it works with a VPN. For some reason doesn't work without one.
Where will the problems be available for upsolving?
Cses is usually where it's the easiest to practice, but I don't know the exact date that it will be uploaded.
Doesn’t cses only have BOI problems till 2021? If I’m not wrong?
BOI Archive
looks like they upload every year
I’ve created a partially complete Codeforces gym to upsolve the problems from the contest, and you can find it here.
However, I’m currently missing solutions for a few problems and would greatly appreciate any help. If anyone has the full solutions for problems 2 and 3 from Day 1, and would be willing to share them, it would help me finalize the gym and move the problems over to Polygon. Everything else is ready to go.
The gym currently includes problems "Acronym," "Developer," "Exponents", and "Gingerbread."
Edit 2: Looks like all the problems are now on qoj.ac: day 1, day 2!
The problems are available on Eolymp.