|
![]() ![]()
![]() ![]() |

The EUC is a new contest that was launched last year, so this is the second edition. It brings together the top teams from 4 European regionals, providing them both an additional qualification path to the ICPC World Finals (detailed rules), and a significant onsite competition of its own, giving many teams who will not make it to the World Finals an opportunity to meet other students and enjoy the atmosphere of a big international competition, while keeping the travel costs in check. I am very happy to support this competition by volunteering as a judge for the second time!
We are also running a mirror contest on Codeforces, so come try it in a few hours! I think the problems are quite nice.
- Facebook✓
- Google+✓
- Instapaper✓
- Tweet✓

Among the people born in the 21st century, the Peking University team was very fast on the easier problems, had very few incorrect attempts, in the end earning the championship title with a huge margin of almost 300 penalty minutes. Big congratulations to them and to all medalists! And of course huge thanks to all #ICPCAstana organizers, you did a great job!
From the 12 medalists, 1 came from the Northern Eurasia division, 2 from the North America division, 4 from the Asia East division and 5 from the Asia Pacific division. Is it the best result ever for the Asia Pacific division?.. Sadly, the ETH Zürich team and other teams from our Europe division stopped at 7 problems solved and therefore just shy of the medal boundary.
Problem D in this round required a nice and somewhat unexpected observation. You are given n segments (n<=200000) on the number line. You need to pick one number from each segment, and then pair up some of those numbers in such a way that two numbers in a pair always add up to the given sum s. What is the maximum number of pairs you can form?One more thing that I did not mention yet about the ICPC World Finals Astana is the CLI symposium. It is a collection of talks by the people that run various aspects of the competitive programming community, for example this year's speakers were Nikolay Kalinin, Riku Kawasaki, Suhyun Park, Antti Laaksonen, Gennady Korotkevich, Andrey Stankevich, Yonghui Wu, Miguel Revilla Rodriguez, Joshua Andersson, Matt Ellis and Christian Yongwhan Lim. You can watch their talks on the ICPC Live channel as well: 1, 2, 3. They are not necessarily at the level of a TED talk, but I think they can provide interesting insights into the thinking of the speakers and into the functioning of the community.
Thanks for reading, and check back next week!
- Facebook✓
- Google+✓
- Instapaper✓
- Tweet✓

It is finally getting serious tomorrow, with the ICPC World Finals 2024 starting around 11:00 Astana time (official live stream, scoreboard and problems, mirror contest, list of teams 1, list of teams 2). As usual, there are many very strong teams that have been practicing specifically for this event, so it is quite hard to predict tomorrow's standings. We can just relax and enjoy watching the contest. But of course go #ETH!
As the custom goes (2017, 2018, 2019, 2020, 2022), I have teamed up with Kevin and Nikolay to participate in the mirror and stream the proceedings. Here is a link to our stream, and in case something goes wrong, you can look for new instances of the stream on my Youtube channel and/or my Twitch. Tune in tomorrow around 11:00 Astana time (in the past, the round has started both a bit later and a bit earlier)!- Facebook✓
- Google+✓
- Instapaper✓
- Tweet✓

One other thing already going on for three days is the ICPC Quest, which this post is also part of. There are various challenges aimed at people getting to know one another, and creating more content about the World Finals, and completing those challenges gets one some plush camels. I did not take part in it in the past, but I've decided to give it a go this year, and it's fun! I'm including #ICPCAstana in this post to fulfill one of the quest tasks :)
Thanks for reading, and check back tomorrow!
- Facebook✓
- Google+✓
- Instapaper✓
- Tweet✓

There will be no contests this week, but this is just a small break before another huge event, as ICPC World Finals in Astana is already happening next week (website, brochure, some news on the left). So expect this blog to become a travel blog again, and we'll likely be organizing another stream of us solving the round in parallel, even though the meaning of "us" is unclear given that tourist is now a judge.
- Facebook✓
- Google+✓
- Instapaper✓
- Tweet✓

- Facebook✓
- Google+✓
- Instapaper✓
- Tweet✓

First, consider the case n=2. If the permutation is an identity permutation, we can just print w=0, and we're done. The only other case is when the permutation is a swap. Even in that case, there is actually not that many options for what we can do on the first pass. First, notice that we must not lose information after the first pass: all 2n possible sets of values of ai before and after the first pass must be in a one to one bijective relationship, as otherwise we would have two initial states map to the same state after the first pass, and since our program is then restarted and we have no other memory except the current state of ai, we would not be able to distinguish those two initial states, but the end results for them must be different.
Therefore after reading a0 we have only two options: we either do not change it, or we change it to the opposite value a0+1 (here and below we use addition modulo 2). But note that adding 1 on the first pass makes no difference if we have a second pass, since we could just add 1 on reading in the second pass instead. Therefore, without loss of generality we do not change a0 on the first pass. For a1 we have a few more options since we can also take a0 into account. More specifically, in each of the two cases a0=0 and a0=1 we either keep a1 unchanged or add 1 to it. If we take the same decision in both of those cases, then the whole first pass has been useless, as we can make the same adjustment on reading in the second pass. Therefore we must take different decisions. Which one we take in which case is also irrelevant, since they differ by adding a constant, which can be done in the second pass instead. Therefore once again we can essentially only do one thing: write a1+a0 as the new value for a1.
By the same argument, on the second pass where we go from right to left we keep a1 unchanged and write a1+a0 as the new value for a0, and so on. After three passes, we actually obtain the well-known algorithm to swap two values without using additional memory (note that + and - are the same thing modulo 2):
- a1=a1+a0
- a0=a1-a0
- a1=a1-a0
This means that we have applied the swap as needed. We could only do one thing for n=2, but this thing turned out to be exactly what we needed when w=3!
Now consider the case of higher n, but when the given permutation is the reverse permutation. The reverse permutation consists of independent swaps: we need to swap the 0th and the (n-1)-th bits, the 1st and the (n-2)-th, and so on. Therefore we can simply apply the above trick for swapping a pair for all of those swaps, and do it in parallel during the same 3 passes, therefore solving this case with w=3 as well.
We can do the same for any permutation that consists of independent swaps — in other words for any permutation of order 2. But how to handle the general case? It turns out that any permutation can be represented as a product of two permutations of order 2! To see how to do it, we can first notice that it suffices to represent a cycle of arbitrary length as such a product, as several cycles can be handled independently. We can then consider what happens when we multiply the following two permutations: the first permutation swaps the 0th and 1st elements, then the 2nd and 3rd elements, and so on; the second permutation keeps the 0th element in place, swaps the 1st and 2nd elements, the 3rd and 4th elements, and so on. It is not hard to see that every swap of the second permutation will swap two elements of different cycles, which means that those cycles will merge, which in turn means that in the end we will have one big cycle. The nodes along this cycle will not come in the order 0, 1, 2, ..., but it does not matter since we can renumber them arbitrarily to obtain a solution for any cycle.
This fact can be used to solve the general case with w=6 by applying each of the two permutations of order 2 using 3 passes. However, we can do one better and achieve w=5 if we notice that the last pass of applying the first permutation and the first pass of applying the second permutation can be merged into one. In order to see this, notice that we can make both of those passes go from left to right, and then each of them would find a new value for a certain bit using the old values of this bit and all previous bits; since our memory is not erased within one pass, we might as well compute the new value for that bit for the first pass of the second permutation using the values that would have been computed by the last pass of the first permutation instead, and write that one directly.
Going from w=5 to the optimal w=3 is a bit more technical, so I will not describe it in detail. To come up with my own solution for w=3 I relied on a more sophisticated version of the argument from the solution for n=2. After the second pass, we must leave the bits in such a state that the final state of each bit depends only on the state of this bit and the previous bits (since the third pass goes from left to right). And there are actually not too many different things that we can do during the first pass if we need to be able to leave the bits in such a state after the second pass. You can also check out alernative approaches in this Codeforces comment, or in the editorial.
The second problem came from Codeforces: you are given an empty n times m grid (4 <= n, m <= 10). You need to write all integers from 1 to nm exactly once in the grid. You will then play the following game on this grid as the second player and need to always win. The first player takes any cell of the grid for themselves. Then the second player takes any cell that is not taken yet, but is adjacent (shares a side) to a taken cell, for themselves. Then the first player takes any cell that is not taken yet, but is adjacent (shares a side) to a taken cell, for themselves, and so on until all cells are taken. The second player wins if the sum of the numbers of the cells they have in the end is smaller than the sum of the numbers of the cells of the first player. I did not solve this problem, but it turned out that I was on the right track :) On the left you can see the picture I had in my notes during the contest, where I placed 1, 2 and 3, and was trying to prove that if the starting player takes one of them, I can always take the remaining two for myself. On the right you can see the picture from the excellent editorial, to which I refer you for the actual solution, as I do not have much to add :)Thanks for reading, and check back for this week's summary!
- Facebook✓
- Google+✓
- Instapaper✓
- Tweet✓

- n=2
- the given permutation is a reverse permutation
Can you see how to move from those subtasks to a general solution with w<=5?
Codeforces ran Pinely Round 4 on Sunday (problems, results, top 5 on the left, analysis). As Um_nik rightly points out, tourist has continued his amazing run of form, and is potentially one more win away from crossing the magical boundary of 4000. Very well done!I also share Yui's sentiment: it is very cool and quite surprising that problems H and I can in fact be solved. During the contest, I did not manage to make any significant progress in both of them in about 1 hour and 15 minutes I had left after solving the first 7. On the other hand, the (nicely written!) editorial almost makes them look easy :)
If you have not checked out the editorial yet, you can try crack problem I yourself. The statement is quite simple and beautiful: you are given an empty n times m grid (4 <= n, m <= 10). You need to write all integers from 1 to nm exactly once in the grid. You will then play the following game on this grid as the second player and need to always win. The first player takes any cell of the grid for themselves. Then the second player takes any cell that is not taken yet, but is adjacent (shares a side) to a taken cell, for themselves. Then the first player takes any cell that is not taken yet, but is adjacent (shares a side) to a taken cell, for themselves, and so on until all cells are taken. The second player wins if the sum of the numbers of the cells they have in the end is smaller than the sum of the numbers of the cells of the first player.
Given that the first player can choose the starting cell arbitrarily, it seems quite hard to believe that the second player can have any advantage. Can you see the way?
- Facebook✓
- Google+✓
- Instapaper✓
- Tweet✓

Even though the problem does not ask for it, it is actually super helpful to think where will the final big slime be located. For me, this would have probably been the hardest part of solving this problem. Why should one think about the final position if the problem only asks about the final time?..
After studying a few examples, one can notice that the final position is always equal to the average of the starting positions of the slimes. Having noticed this, it is relatively easy to prove: consider the function sum(ai*wi) where ai is the position of the i-th slime, and wi is its weight, and consider two slimes (ai,wi) and (aj,wj). The first one contributes -wi to the velocity of the second one, while the second one contributes wj to the velocity of the first one. Therefore together they contribute -wi*wj+wj*wi=0 to the velocity of value sum(ai*wi), therefore that sum stays constant. And it also does not change when two slimes merge, therefore it is always constant and has the same value for the final big slime.
Now is the time for the next cool observation, this one is a bit more logical though. Consider the last two slimes that merge. They split the original slimes into two parts. What happens to the weighted averages of the positions of those two parts sum(ai*wi)/sum(wi)? By the same argument as above, influences within each of the parts on that average cancel out. The influences of the parts on each other do not cancel out though, but we can easily compute them and find out that those two averages are moving towards each other with constant velocity equal to the total weight, in other words k.
Therefore if we know which two parts form the two final slimes we can find the answer using a simple formula: (sum(ai*wi)/sum(wi)-sum(aj*wj)/sum(wj))/k, where j iterates over the slimes in the first part, and i iterates over the slimes in the second part.
And here comes the final leap of faith, also quite logical: the answer can actually be found by finding the maximum of that amount over all ways to choose a prefix and a suffix as the two parts. This can be proven by noticing that the difference between averages starts decreasing slower than k if some slimes merge across the part boundary, therefore the number we compute is both a lower bound and an upper bound on the actual answer.
We have not yet dealt to the fact that we have to choose k slimes out of n, but seeing the above formula it is pretty clear that we should simply take a prefix of all available slimes for the sum over j, and a suffix of all available slimes for the sum over i. Now all pieces of the puzzle fit together very well, and we have a full solution.
The second problem I mentioned came from Universal Cup: you are given a string of length n<=500000. We choose one its arbitrary non-empty substring and erase it from this string, in other words we concatenate a prefix and a suffix of this string with total length less than n. There are n*(n+1)/2 ways to do it, but some of them may lead to equal strings. How many distinct strings can we get?A natural question to ask is: how can two such strings be the same? If we align two different ways to erase a substring of the same length that lead to the same result, we get the following two representations of the same string:
abcd=aebd
where in one case we delete the substring c, and in the other case we delete the substring e to obtain the result abd. We can notice that such pairs of equal prefix+suffix concatenations are in a 1:1 correspondence with pairs of equal substrings within the string (two occurrences of the substring b in the above example). It is not true though that our answer is simply the number of distinct substrings, as we have merely proven that the sum of c*(c-1)/2 over all repeat quantities c of equal substrings is the same as the sum of d*(d-1)/2 over all repeat quantities d of equal prefix+suffix, but that does not mean that the sum of c is the same as the sum of d.
However, this makes one think that probably the suffix data structures, such as the suffix tree, array or automaton, will help solve this problem in the same way they help count the number of distinct substrings. This turns out to be a false path, as the actual solution is much simpler!
Consider the middle part of the above equation (bc=eb), and let us write out an example with longer strings for clarity:
abacaba
abacaba
We can notice that the following are also valid ways to obtain the same string:
abacaba
abacaba
abacaba
abacaba
Thanks for reading, and check back next week!
- Facebook✓
- Google+✓
- Instapaper✓
- Tweet✓

Problems A and B both had short solutions and were quick to implement, but required one to come up with a beautiful idea somehow. When Riku was explaining their solutions during the broadcast, I was amazed but could not understand how to come up with them :) One way to do it, at least for problem A, was to actually start by assuming the problem is beautiful, and to try coming up with some beautiful lower or upper bound for the answer, which can turn out to be the answer.
To test if you can walk this path, here is the problem statement: you are given n<=250000 slimes on a number line, each with weight 1. You need to choose k of them, all others will be removed. Then, they will start moving: at each moment in time, every slime moves with velocity r-l, where r is the total weight of all slimes to the right of it, and l is the total weight of all slimes to the left of it. When r-l is positive, it moves to the right, and when it is negative, it moves to the left. Since this rule pushes the slimes towards each other, sometimes they will meet. When two or more slimes meet, they merge into one slime with weight equal to their total weight, which continues to move according to the above rule. Eventually, all slimes will merge into one stationary slime, suppose this happens at time t. What is the maximum value of t, given that you can choose the k slimes to use freely?
Problem D turned out to be equivalent to an old Codeforces problem applied to the inverse permutation. Most of this week's finalists have participated in that round or upsolved it, so it was not too unfair. The top two contestants ecnerwala and zhoukangyang did solve the Codeforces problem back in 2022, but did not remember it, and implemented the solution to D from scratch (even though of course having solved the old problem might have helped come up with the correct idea here). ksun48 and heno239 in places 3 and 4 did copy-paste their code from 2022.
Problems C and E involved a bit more code and effort to figure out all details, but one could make gradual progress towards a solution when solving them, instead of having to pull a beautiful idea out of thin air. Were I actually participating in this round, I would most likely spend the most time on, and maybe even solve those two problems.
Overall, this was a very nice round, and I'm looking forward to more AGCs in 2024 to try my hand at more amazing problems!
On the next day after the AWTF, the 3rd Universal Cup Stage 4: Hongō took place (problems, results, top 5 on the left). 8 out of 9 participants from the first three teams (congrats!), which coincidentally are also the first three teams in the season ranking, were in Tokyo, so Riku and Makoto have organized an onsite version of this stage at the AtCoder office. Solving a 5-hour contest with your team in person instead of online is already much more fun, but having other teams in the room and discussing the problems with them right after the round is even better. I guess I'm still yearning for the Open Cup days :)I was solving this round together with Mikhail and Makoto. Thanks a lot Makoto for briefly coming out of retirement to participate, it was great fun solving this round together, and I can confirm that you're still very strong! Maybe we can have another go next year.
Problem N was not very difficult (I spent at least half an hour without any success, explained the problem to Makoto and he solved it almost immediately), but still enjoyable: you are given a string of length n<=500000. We choose one its arbitrary non-empty substring and erase it from this string, in other words we concatenate a prefix and a suffix of this string with total length less than n. There are n*(n+1)/2 ways to do it, but some of them may lead to equal strings. How many distinct strings can we get?
Thanks for reading, and check back next week.
- Facebook✓
- Google+✓
- Instapaper✓
- Tweet✓