Booklet 2012 Bubble Cup Serbia
Booklet 2012 Bubble Cup Serbia
Booklet 2012 Bubble Cup Serbia
Belgrade, 2012
Scientific committee:
Andreja Ili
Andrija Jovanovi
Milan Vugdelija
Mladen Radojevi
Miroslav Bogdanovi
Draen ari
Dimitrije Filipovi
eljko Nikolii
Milan Novakovi
Qualification analyses:
Nikola Milosavljevi
Boris Grubi
Duan Zdravkovi
Dimitrije Dimi
Uros Joksimovic
Milos Biljanovic
Dejan Pekter
Bartek Dudek
Linh Nguyen
Petar Velikovi
Ivan Stoi
Goran ui
Bartosz Tarnawski
Vanja Petrovi Tankovi
Vladislav Haralampiev
Aleksandar Ivanovi
Stjepan Glavina
Patrick Klitzke
Teodor Von Burg
Filip Paveti
Predrag Miloevi
Danilo Vunjak
Marko Bakovi
Cover:
Sava ajetinac
Typesetting:
Andreja Ili
Proofreader:
Andrija Jovanovi
Volume editor:
Dragan Tomi
Contents
Preface ...................................................................................................................................... 6
About Bubble Cup and MDCS ...................................................................................................... 7
Bubble Cup Finals 2012 ............................................................................................................... 8
Problem A: Good sets ......................................................................................................................... 9
Problem B: Wheel Of Fortune ........................................................................................................... 13
Problem C: MaxDiff .......................................................................................................................... 15
Problem D: Cars................................................................................................................................ 18
Problem E: Triangles ......................................................................................................................... 22
Problem F: Olympic Games ............................................................................................................... 25
Problem G: Matrix ............................................................................................................................ 27
Problem H: String covering ............................................................................................................... 31
Problem I: Polygons .......................................................................................................................... 34
Qualification ............................................................................................................................ 37
Problem R1 01: November Rain (code: RAIN1) .................................................................................. 39
Problem R1 02: Ambiguous Permutations (code: PERMUT2) .............................................................. 41
Problem R1 03: Roll Playing Games (code: RPGAMES) ....................................................................... 43
Problem R1 04: Manhattan Wire (code: MMAHWIRE) ....................................................................... 45
Problem R1 05: Spheres (code: KULE) ................................................................................................ 48
Problem R1 06: Sightseeing (code: GCPC11H) .................................................................................... 52
Problem R1 07: Segment Flip (code: SFLIP) ........................................................................................ 54
Problem R1 08: K12 - Building Construction (code: KOPC12A) ............................................................ 57
Problem R1 09: Its a Murder! (code: DCEPC206) ................................................................................ 59
Problem R1 10: Words on graphs (code: AMBIG) ............................................................................... 61
Problem R2 01: Zig-Zag Permutation (code: ZZPERM) ........................................................................ 63
Problem R2 02: DEL Command II (code: DELCOMM2) ........................................................................ 65
Problem R2 03: Boxes (code: BOX) .................................................................................................... 67
Problem R2 04: Cryptography (code: CRYPTO) ................................................................................... 72
Problem R2 05: Slow Growing Bacteria (code: SBACT) ....................................................................... 74
Problem R2 06: Reverse the sequence (code: REVSEQ) ...................................................................... 76
Preface
Dear Finalist of BubbleCup 5,
Thank you for participating in the fifth edition of the Bubble Cup. On behalf of Microsoft Development
Center Serbia (MDCS), I wish you a warm welcome to Belgrade and I hope that you will enjoy yourself.
MDCS has a keen interest in putting together a world class event. Most of our team members participated
in similar competitions in the past and have passion for solving difficult technical problems.
This edition of the Bubble Cup is special. It is its fifth anniversary and it is the most international event that
we have had so far. Not only do we have the participants from the region (Bulgaria, Croatia, Serbia) but
teams from Germany and Poland fought their way to the Finals too. This means that BubbleCup is reaching
more and more fans every year.
Given that we live in a world where technological innovation will shape the future, your potential future
impact on humankind will be great. Take this opportunity to advance your technical knowledge and to build
relationships that could last you a lifetime. I wish you all warm welcome to Belgrade.
Thanks,
Dragan Tomi
MDCS Group Manager/Director
Microsoft Development Center Serbia (MDCS) was created with a mission to take an active part in
conception of novel Microsoft technologies by hiring unique local talent from Serbia and the region. Our
teams contribute components to some of Microsofts premier and most innovative products such as SQL
Server, Office & Bing. The whole effort started in 2005, and during the last 7 years a number of products
came out as a result of great team work and effort.
Our development center is becoming widely recognized across Microsoft as a center of excellence for the
following domains: computational algebra engines, pattern recognition, object classification, computational
geometry and core database systems. The common theme uniting all of the efforts within the development
center is applied mathematics. MDCS teams maintain collaboration with engineers from various Microsoft
development centers around the world (Redmond, Israel, India, Ireland and China), and Microsoft
researchers from Redmond, Cambridge and Asia.
Taken from xkcd.com A web comic of Romance, Sarcasm, Math, and Language
Finals 2012
The finals of BubbleCup 5 were held on September 8th 2012, with 17 teams competing at the Faculty of
Electrical Engineering in Belgrade. There were 9 problems and five hours to solve them.
The were no changes to the rules from the previous years. As a reminder: the team which solves the most
problems wins. In case of ties, the team with less penalty points (gained for incorrect submissions and
deducted based on qualification results) is preferred. Programming style is not taken into account.
The difficulty of the problems was relatively balanced no problem was solved by more than 12 teams
(unlike last year, when 3 problems were solved by every team), and one problem remained unsolved. The
accent was mostly on problems which required original thinking, with only a few that were tricky to
implement.
14
12
10
8
6
4
2
0
Good Sets Wheel Of MaxDiff
Fortune
Cars
Triangles Olympic
Games
Matrix
String Polygons
covering
Cars
Triangles Olympic
Games
Matrix
String Polygons
covering
The first accepted solution - Silver lightning: koko koko euro spoko (Poland)
The shortest accepted solution - Vertipaq coders: H-Rast (Croatia)
The most persistent team - while (! accepted): The Code Breathers (Gemany)
BubbleCup friend - The best mentor: Dusko Obradovic, team Gimnazija Sombor (Serbia)
ID
A
B
C
D
E
F
G
H
I
Problem Name
Good Sets
Wheel Of Fortune
MaxDiff
Cars
Triangles
Olympic Games
Matrix
String covering
Polygons
10
Statement:
Let be the set
properties:
, where
a)
is a subset of ;
b) For every , if belongs to , then
doesn't belong to ;
c) No other set can have properties a) and b) and a greater number of elements than ;
For example, if
good, while
superset of ).
, then
is not good (note that set
and
Input:
The first and only line of input contains two integers
and , separated with one empty space,
representing cardinality of the set and the given base , respectively.
Output:
Output contains only one line with two integers, separated with one empty space: the number of elements
in every good set and number of zeros at the end of the total number of good sets in base , respectively.
Example input:
Example output:
12 3
8 1
Example explanation:
All good sets consist of 8 elements and there are 6 of them - 6(10) = 20(3).
Constraints:
Number
is a prime number.
, because
It remains to count chains of each different length, add up maximal numbers of elements for each chain,
and multiply ways to choose such elements from each chain. Actually, instead of computing the exact
number of ways to form a good set, it is required only to compute how many times this number is divisible
by a given prime number .
12
Statement:
You are on a quiz show playing the game Wheel of Fortune. The wheel has fields of the same size, and
each field
is associated with a value:
. Each time you spin the wheel you have
equal probability of hitting any of the fields. You will spin the wheel times. When you spin the wheel
for the -th time and it stops on field , if it is your first time hitting that field,
dollars is added to your
prize and field gets marked. If the wheel stops at a marked field, meaning you've hit that field in some of
your previous spins (
), your score does not increase.
What is the expected value of the prize you'll take home?
Input:
The first line contains two integers, number of fields on the wheel, and number of times you get to
spin the wheel. The following
lines contain one integer each, representing values of the fields .
Output:
Output contains exactly one real number expected value of your overall prize, rounded to 5 decimal
places.
Example input:
Example output:
2 2
10
20
22.50
Constraints:
13
Given that we have fields of the same size, and we are making random draws (i.e. wheel spins), it is
obvious that for each field of the wheel we have the same binomial distribution over the number of hits
after
spins:
( )
Here
hits after
spins, and
Now we can write the distribution over prize value for each field:
(
In order to avoid dealing with binomial coefficients, we can rewrite the above distribution in simpler terms:
(
so we end up with:
(
) )
solution.
14
Problem C: MaxDiff
Problem C: MaxDiff
Author: Milan Novakovi
Statement:
You are given an array of integers of length . We will define
as the sum of absolute differences
between all pairs of consecutive elements in . More formally, assuming that is zero-based:
|
|
Your task is to find the permutation
of the array
is maximized.
Input:
The first line of input will contain one integer , representing the size of the array . The second line will
contain space-separated integers, representing the elements of the array.
Output:
The first and only line of output should contain a single integer equal to the largest sum of differences of
consecutive elements obtainable from as described in the problem statement.
Example input:
Example output:
3
2 3 5
Example explanation:
There are six possible ways to reorder the array:
The sums of differences are then respectively
.
and , and the largest among them is .
Constraints:
Problem C: MaxDiff
which the elements are sorted in a zig-zag manner, i.e. it will not contain a triple of consecutive elements
such that
(or
). Proving this is easy: if we have a
triple satisfying this condition, we can just pull out its middle element and place it at the end of the array
it is trivial to verify that cannot decrease after this transformation.
The other fact is slightly harder to notice. Lets denote the median of with . (A reminder: the median of
an array is the middle element of the sorted array if the number of elements is odd, and the average of the
two middle elements if the number of elements is even). Clearly depends only on the elements of and
not on the permutation. We will prove the following:
Lemma. There is an optimal solution in which there are no two consecutive elements that are either both
larger or both smaller than the median.
Proof. The first thing to notice here is that, due to the zig-zag principle discussed above, an optimal
solution cant contain a sequence of exactly two consecutive elements on the same side of the median.
Lets assume that there are at least three such consecutive elements. It is easy to see that we can always
pick exactly three consecutive elements from this sequence such that
. Since the
rest of the array now has at least two more elements that are under the median than elements that are
over it, we can use the same reasoning to conclude that somewhere else in the array there are three
consecutive elements under the median, ordered as
. Since
(the former is over the median and the latter under it), we can swap these two elements and get a solution
that preserves all the inequalities and is strictly better than the previous one.
Now we have enough information to deduce the most important statement:
If the order of elements in A satisfies the two principles described above, its value of S is
|
where
is the median of A.
It should be clear that this holds from the following argument: since for all
arent on the same side of the median, their absolute difference is |
|
|. For each element except the first and the last one the term |
final sum, while for the two edge elements it appears just once.
elements
and
| |
|
| appears twice in the
This gives us the final step in the solution: since all terms in the sum are non-negative, we just have to
| |
|. If the total number of elements is even, we pick the two
minimize the value |
middle elements for the ends otherwise the zig-zag property would not hold. If it is odd, we pick the
median element at one end and the element closest to it by absolute value at the other.
Note that we dont even have to generate the exact permutation, since all permutations
constructed
in this way will have the same value
and the above discussion gives us the guarantee that
permutations which dont satisfy these conditions cannot possibly result in a better solution.
The implementation ends up being very simple: first we find the median of the array A, then we find the
edge elements as described in the previous paragraph, and finally we sum up the absolute differences of
the elements from the median, multiplying by two for all except the leftmost and the rightmost element.
There are still some traps that need to be avoided edge cases with a very small number of elements need
to be dealt with, the solution has to be kept in a 64-bit value, repeating values can pose a problem for
16
Problem C: MaxDiff
certain implementations. However, none of that should present a serious challenge for any competitor with
decent technique.
Complexity
There is a choice for the algorithm used to calculate the median. The simplest way is to sort all the
elements and pick the one(s) in the middle, which takes
time. We can do better the wellknown quickSelect algorithm gives expected
time. Although its running time depends on the pivot
choice and its worst-case complexity is
, median-of-three or just random pivot choice should be
enough since none of the test cases targeted this scenario (at least not intentionally). For the more
paranoid contestants, the pivot can be chosen using the median-of-medians algorithm, which guarantees
running time but is tricky to implement and slower on average than simple quickSelect.
The rest of the algorithm can be done in a single pass of the array, giving an overall
of the algorithm. The memory complexity is obviously
.
17
time complexity
Problem D: Cars
Problem D: Cars
Author: Mladen Radojevi
Statement:
There are cars parked at the parking lot and a new car is arriving. The parking lot is a space between two
walls and cars are parked along one line between those walls. The driver will park his car if there is a free
parking spot that is long enough (at least as long as the car). Otherwise, he will have to move a few cars in
order to make appropriate space for his car. The car can be moved to the left or to the right along the
parking lot, but at most until it reaches a wall or another car.
Your task is to find the minimal total distance by which currently parked cars have to be moved in order to
provide enough space for the arriving car.
Input:
The first line of input contains three space-separated integers ,
and
. They denote the number of
cars already parked, the coordinate of the left wall and the coordinate of the right wall, respectively. Each
of the following lines contains two integers, describing a parked car: the coordinate of the leftmost
point of the car, and the length of the car. The last line of the input contains one integer
, the
length of the arriving car.
Output:
Output contains only one line with one integer the sum of distances by which parked cars have to be
moved to provide enough space for the arriving car. If a solution doesnt exist the output should be
.
Example input:
Example output:
4 0 22
2 3
7 3
11 2
16 4
7
Example explanation:
The best way is to push the second car to the left by 1, the third car to the left by 2 and the fourth car to
the right by 2. It will create an empty space of length 7, so the new car can be parked there. The sum of all
movement lengths is 5 (= 1 + 2 + 2).
18
Problem D: Cars
Constraints:
Lets enumerate the cars with 1 to from left to right. (To be able to do that, we will need to sort the array
of cars first). Consider each car in turn. For each car , find the first car
such that the sum of free
parking spots between and is greater than the length of the new car. For each such pair
we will find
the optimal solution, and then use these to compute the global minimum.
Lets consider a given pair of cars
. In the case that the pair
also satisfies the total empty
length constraint, we can narrow down the search space by removing car from the set of cars for which
we will consider moves. We will repeat this process as long as removing the leftmost car will still satisfy the
total empty space length constraint. Lets denote the leftmost car remaining in this set with .
such that
whichever car ( or ) is closer to it, in order to reduce the total distance covered. In this way, the upper
bound on the distance any given car can move is
other direction (to the car which is farther away from it) this upper bound would be greater.
Lets define four values for every car:
total cost for moving all cars from 0 to (inclusive) to the left wall.
Another pair of arrays
, representing free space and total cost of moving to the right wall.
These values can be pre-computed in
We would like to compute the cost of moving all cars between and away from the middle ( ), without
moving any other cars.
19
Problem D: Cars
m
Consider only cars
(The rightmost car moved to the left) and
. We will separately calculate the cost
of moving cars to the left and to the right. The cost can be calculated in the following way:
The cost of moving car
to
The only issue here is that we may have created more space than what is needed for the new car. To
reduce the cost we should first compare
and
(the number of cars we moved to the left and
the number of cars we moved to the right).
Let
be the sum of empty spaces between cars and , and let be the space we created for the new car.
20
Problem D: Cars
In the case that we moved more cars to the right than to the left the same logic applies using the values
from
and
After calculating
for each car as a first car ( ), we should easily be able to pick the best one.
The time complexity of the solution is dominated by the initial sort the rest of the algorithm is linear. This
means that the overall time complexity is
.
21
Problem E: Triangles
Problem E: Triangles
Author: Mladen Radojevi
Milan Vugdelija
Statement:
You are given an array of positive integers. Find the maximal substring (i.e. a subset of at least three
consecutive elements of the array) so that any three distinct elements from that substring can form the
sides of a triangle. Also, find the maximal subsequence (a subset consisting of at least three elements, not
necessarily consecutive) with the same property.
Input:
The first line of input contains one integer , the number of elements in the array. The next
the elements of the array.
lines contain
Output:
Output consists of exactly two lines, each containing one integer the length of the maximal substring and
the maximal subsequence with the property described above, respectively. If such substring or
subsequence doesnt exist, the corresponding value is zero.
Example input:
Example output:
5
60
30
20
40
60
3
4
Constraints
Elements of the array are positive integers, each less than or equal to
time (or
Part a (substring):
To verify that some substring fulfills the requirement, it is enough to check if the sum of two smallest
numbers in a substring is greater than the largest number in that substring. Indeed, if the inequality holds
for these three elements, it will hold for any three numbers in that substring.
There are several ways to find the length of the longest such substring, two of which will be explained here.
22
Problem E: Triangles
Solution 1:
Suppose that we want to check if there exists a substring of length with the described property. We can
divide input array into slots of length (the last slot may have less than elements). For each slot
, we can compute the following arrays:
-
Prefix maximum:
Suffix maximum:
Prefix minimum:
Suffix minimum:
With this pre-calculation, we can find the maximum, minimum and second minimum of any substring of
input array of length in constant time. Namely, any substring of length covers entirely one slot or lies in
two consecutive slots, so min and max are straightforward to compute using suffix arrays of the left slot
and prefix arrays of the right slot, while computing second min requires several comparisons between
minima and second minima of two parts of the substring.
Acting as described, it is possible to check all substrings of length
gives us an
algorithm for the original problem.
Solution 2:
We start with the substring consisting of the first three elements of the input array. If the current substring
has the required property, we move the right boundary of the substring forward, introducing a new
element into it; otherwise we move forward the left boundary of the substring, removing one element
form the substring.
To check if the substring has the triangle property, we can use one heap that extracts maximum, and one
that extracts minimum - lets call the heaps and respectively. When the right boundary moves, we just
put a new element into both heaps. Moving the left boundary requires removing one particular element
from both heaps. Instead of removing that element immediately, we can use two auxiliary heaps (again,
one for max and one for min, call them
and
) and put the element that should have been removed
there. As long as that element is not equal to max of the heap , it doesnt matter if it is present in the
heap or not. So every time we extract the max of heap , we also extract the max of
; if they are not
equal, the max is regular and we can use it (we just put back the max of
); if the two maxima are equal,
we do the (delayed) removal from both and
, and get another max from both until they differ. We do
the same with heaps and
for extraction of the minimal element.
Getting min/max from the heap and putting a new element into all 4 heaps requires
time, so we
can check one particular substring in logarithmic time. Since after each check one of the substrings
boundaries moves forward, there are
substrings to check, so the total running time is again
.
Part b (subsequence):
It is easy to prove that if some elements of a sorted array form a subset with the described property, then
the entire segment (from minimal to maximal element of the subset) also has the property. So, , the
maximal subset of the original array with the described property is a substring of the sorted array.
Therefore, to solve part b, it is enough to sort the input array and then search for the longest substring
23
Problem E: Triangles
using (any) solution of part a. The running time of such algorithm would be
log n) for finding the longest substring, which gives
in total.
It is also possible to find the longest substring with the given property in a sorted array more directly.
Obviously, the two smallest elements are the first two elements of a substring, and the largest is the last
one, so there is no need to use heaps or auxiliary prefix/suffix arrays to find minima and maxima of a
substring. The running time in this case is still
due to sorting, even though finding the longest
substring in a sorted array can be done in linear time.
24
Statement:
Young boy, Oliver, has watched the Olympic Games this year for the first time. The number of countries
which participated in the Olympics is . There are
different sports and each country had its own
representative in some of the sports. In each sport the gold medal is won by exactly one country among
the ones that have representatives for that sport. And, of course, for every sport there is at least one
country which competes in it.
Oliver noticed that a small number of countries won a huge number of gold medals, and that a lot of
countries didnt win any. Now, he is wondering what could be the minimal difference in the number of gold
medals between the country which took the most and the country which took the least. Oliver is still too
young to figure out the answer to this question, so please help him.
Input:
The first line contains , the number of participating countries. The second line contains , the number of
sports. The third line contains the total number of competitors, . Each of the next m lines contains two
integers, and , which mean that country had a representative in sport .
Output:
Output contains only one integer the minimal possible difference in the number of gold medals between
the country which took the most gold medals and the country which took the least.
Constraints:
No pair
for each
is contained in the input more than once
Example input:
Example output:
3
4
6
0
0
0
1
1
2
0
1
2
2
3
3
25
26
Problem G: Matrix
Problem G: Matrix
Author: Andreja Ili
Statement:
You are given a square binary matrix of dimension
. Elements on the main diagonal are all ones.
th
We want to compute the
power of this matrix (MDCS written in ASCII codes is
). To make things more interesting, we will define binary operations
(addition) and
(multiplication) as the following:
+
0
1
0
0
1
1
1
1
0
1
0
0
0
1
0
1
Output:
th
Example output:
4
1
1
1
2
2
3
3
4
11
8
1
3
4
2
3
1
3
4
Example explanation:
]. Its
th
power is [
], which has
ones in it.
Constraints:
27
Problem G: Matrix
Note:
For two square matrices and with dimensions
is product of these two matrices if:
to vertex
of length .
We have an additional property of the start matrix: elements on the main diagonal are ones. This means
that all of the vertices have loops. In other words, we can circle around any vertex for an arbitrarily long
time. So, if there is a path of length between vertices and , then there is path of length
between
them for every
(we can just append a circle of length
to path). This means that, with the
above property of matrix , we have
if and only if there is a path from vertex
to vertex
Now we can go back to our original problem. In the input we have a directed graph with vertices and
edges, where every vertex has a loop. From the above definition of the element
, we have that
starting from
power of matrix is not going to change. This is very important, because in this way
we have to calculate the -th power, and of course
. The problem can be reformulated as:
find the number of edges in the transitive closure of the given graph ,
i.e. for every vertex calculate the number of vertices that are reachable from it
Nave approach for the transitive closure leads to complexity
28
Problem G: Matrix
vertex separately. A better idea is to find the strongly connected components (SCC) first. In this way,
submatrices for every component have all elements equal to one (so we do not want to waste time
there). After finding the SCCs, we can shrink every component to just one vertex. In this way we can
obtain a directed acyclic graph (DAG).
Things are a little bit easier. If we assume that for every component we have a list of all components that
are reachable from it, we can easily transfer this to the start graph and calculate the final result. But how
can we initialize these lists with the given time constraints?
For DAG we can find its topological sort order. We can initialize the lists for every component in this order,
because it holds that by the time when we are examining some component, all components reachable from
it are already initialized. Let us denote with
the current component for which we want to
initialize the list. Unfortunately, we cannot simply connect all lists from their neighbors, because there
can be some duplicates (see Figure 2 for example). On the other hand, these lists can be
long, so the
union of these sets must require passing through them multiple times.
Figure 2. Example of a topological sort and mask arrays (for the case of 2-bit numbers)
The best way to maintain these lists is to store them in some sort of marked array (when a component is
in the list we are going to mark the corresponding element). If we use simple boolean arrays, complexity
will again be
. Idea is to use bit masks. For every component we are going to store an array
of length
in this
array as
29
Problem G: Matrix
In other words, for each component there is a unique corresponding bit in every array. Now, we can
initialize the array for
by simply
-ing the arrays for its neighbors element-wise (which
represents union). Note that although the complexity remains
, the reduction of the constant
factor is very significant.
Complexity:
In this problem we have quite a pipeline of graph algorithms. First, the complexity of finding SCCs and
building a DAG is
. Finding the topological order has the same complexity. Finally, performing the
dynamic programming approach for initialization of bit mask arrays as described above has
complexity if we use a 64-bit integer type for bit masks. Indeed, every array is going to be iterated for every
component which has an edge directed at the corresponding component for that array. So, for every edge
we have one tour through some array. This brings us to the final complexity of
Test data:
The data corpus for this problem consists of 24 test cases. Test cases are created with one (or more) of the
following methods:
4
10
100
1000
500
2000
2500
3000
3000
3000
5000
4000
3000
5000
5000
5000
5000
5000
5000
5000
5000
1
4500
5000
8
31
5187
1000
125250
161804
127736
5999
36871
193412
161017
67879
182515
9999
59870
194846
179948
196411
189283
188570
184753
1
118341
143657
Comment
test case from problem statement
by hand
Random with
All zeros except on the main diagonal
One in the upper triangle
Random with
Random upper triangle with
Random tree structure
Path with down edges
Expanded SCC graph with
Expanded SCC graph with
Random with
Random tree structure with cross edges
Random tree structure
Random tree structure with down cross edges
Expanded SCC graph with small
Random with
Path with down edges
Random tree structure with cross edges
Random tree structure with down cross edges
Expanded SCC graph with
Only one vertex
Components: SCC, Tree, Path, Random
Components: big SCC, Tree, Path, Random
30
Statement:
We say that string covers string if can be obtained by putting together several copies of string ,
where overlapping between two successive copies of is allowed but the overlapped parts must match.
After connecting these copies the whole generated string must match string .
For example, string
covers string
does not cover , because the last character
You are given string . Write a program that calculates how many strings
way.
in this
Input:
The first and only line of the input contains string .
Output:
Output contains only one integer the number of different strings that cover given string .
Constraints:
Example input:
Example output:
ababab
Now we have the start positions of occurrences for any prefix. Problem is to, in some efficient way, see if
they cover the whole string . For this we must use additional data structure max heap. In heap we are
going to store the lengths between two successive positions - gaps. When we remove some occurrence, we
will remove two distances / gaps (from prior to current one and from current one to next occurrence) and
add the new one which is the sum of the removed ones (from prior to next). Finally, we can state that
current prefix covers the whole string if and only if the max element in the heap (max distance between
two successive occurrences) is smaller or equal to the prefix length.
==========================================================================================
01 initialization of the suffix array S;
02 sol = 0;
03 for k = 1 to n - 1 do
32
Complexity:
Sorting the suffixes with suffix array takes
time. This can be implemented in the linear time but
in our case this is sufficient. After that for every prefix, in order as in the given string, we are going to
maintain the above segments in linear time overall (in every step we are going to shrink current segment
with only one compering of chars). For heap, every position is going to be added exactly one time and
removed at most one time. Taking all of this in to account we get the final complexity:
.
Test data:
Test corpus consists of 15 test cases. In the random string we can expect only one covering string the
string itself. Many ideas for test generation is to create some recursive string that has many occurrences
of prefixes in it. The worst case for this is to use small number of different chars. Description of the test
data with some comments is given below.
Num
00
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
6
45690
90010
90000
80.000
10.002
98.904
50.003
96.048
99.999
99.999
78950
100.000
1
90.000
100.000
Solution
3
9138
10
10000
1
3334
8242
1
16
1
99.999
3158
1
1
5628
100
Comment
Concatenation of the string
Concatenation of the string
Concatenation of the string
Many with random char
Concatenation of the string
Concatenation of the string
Random concatenation of strings
Concatenation of the string
String is of the form
All chars are the same
Concatenation
Many with random char
Only one char
Concatenation of the string
Concatenation of the string
and
with some
33
Problem I: Polygons
Problem I: Polygons
Author: Miroslav Bogdanovi
Statement:
You are given
points with integer coordinates in the plane. After that you are given
queries.
Each query gives you a list of indices in the originally given set of points. The points in this list form a simple
polygon (one that does not intersect itself). For each query you should output how many points from the
original set are on the inside of the given polygon.
Input:
The first line of the input contains two integers and q, separated with an empty space. Next lines each
contain two numbers, and - coordinates of a point. The lines that come after that each start with a
number , the number of points that form that polygon. The rest of the line consists of space-separated
numbers that represent indices (indices are from to
) of originally given points that form the
polygon.
Output:
You should output lines, one for each query. Output for each query should be just one integer number:
the number of points from the original set on the inside of the polygon given in that query.
Example input:
Example output:
7
0
0
4
4
2
3
2
3
3
1
2
2
0
4
0
4
1
2
3
0 1 3
0 2 3
Example explanation:
First polygon is a triangle whose vertices are
Second triangle has the vertices
and
and
. There is one point on its inside:
. There are two points on its inside
and
.
.
34
Problem I: Polygons
Constraints:
under[A][B] = 3
A
B
directly_under[A] = 1
directly_under[B] = 0
First we sort the points by coordinate, sorting points with equal by . The number of points directly
under each point is easily calculated in linear time from this sorted array.
Now for each point (well call it point A) we take all the points after it in this sorted array (those that have
larger , or equal and larger coordinate) and sort them by angle in respect to point A. We go through
these points in this order (well call the current point B). For each point A we keep an array that counts the
number of times each coordinate has appeared in points B that we went through until now. We keep this
array as a cumulative table in order to be able to do insertions and calculations of the sum of the first
elements in
time for each operation, where
is the maximal value of coordinates
among the set of points. For each point B we do the following:
1. We add 1 to the cumulative table in the position of the coordinate of point B.
2. We calculate the number of points under the line segment A-B as sum in cumulative table to the
position of the coordinate of point B 1.
35
Problem I: Polygons
Not done
Current point
B
A
Done
0 0 1 1 0 1
We respond to each query in the following way. We go through the polygon in clockwise direction and for
each edge, if it goes to the right (the coordinate of its second point is larger than the coordinate of its
first point) we add the number of points under that edge to the sum, otherwise we substract this number
from the sum. For each vertex, if we go through it going to the right (the edge coming into it and the one
going out of it are both to the right) we add the number of points under it to the sum, if we go through it
going to the left we substract the number from the sum.
Clockwise
direction
After going through all edges and vertices of the polygon, each point outside of the polygon is counted zero
times and each point on the inside of the polygon is counted exactly once, which is exactly what we need.
Complexity:
Time complexity of initial calculation is
time. The total complexity is therefore
36
Qualifications
Qualification
The qualification rounds were originally intended to have the same format as in the previous years two
rounds with 10 problems each, with each problem in the first round being worth 1 point and each secondround problem being worth 2 points. The most important change was that the Timus online judge system
was no longer used - Sphere Online Judge (www.spoj.pl) provided the problems and the judging system this
year.
BubbleCup has continued getting more and more popular with every year, and this years edition again
broke all the records, with 109 teams submitting at least one correct solution. It also continued spreading
geographically, with teams from countries such as Germany, Poland, Taiwan and Vietnam participating for
the first time and having lots of success as well one German and one Polish team ended up participating
in the finals.
11
16
21
26
31
36
41
46
51
56
61
66
71
76
81
86
91
96 101 106
The strength of the teams has increased as well. The tasks were not any easier than in the previous
editions, but the results were excellent. This meant that 29 teams solved all problems in the first round,
and 4 of those solved all problems in the second round as well, so for the first time in BubbleCup history
there was a team which got the maximal number of points in the qualifications. This record-breaking team
was Vanja, Nenad and the sandwich maker, and they were quickly followed by S-Force, N0 Ex1t and
koko koko euro spoko.
In the end, the problems from the qualification rounds were solved so well that it was not possible to
separate the teams. So the scientific committee decided to organize a third round for the first time in
BubbleCup history. In the third round, teams with 26 points were called upon to select tasks for each other
to solve, adding yet another strategic dimension to the contest.
The full statistics from the qualification rounds are shown in the tables below:
Num
01
02
03
04
05
06
07
08
09
10
Problem name
November Rain
Ambiguous Permutations
Roll Playing Games
Manhattan Wire
Spheres
Sightseeing
Segment Flip
Building Construction
Its a Murder!
Words on Graphs
Code
RAIN1
PERMUT2
RPGAMES
MMAHWIRE
KULE
GCPC11H
SFLIP
KOPC12A
DCEPC206
AMBIG
Accepted solutions
65
172
50
44
67
58
43
114
104
51
37
Qualifications
Num
01
02
03
04
05
06
07
08
09
10
Problem name
Zig-Zag Permutation
DEL Command II
Boxes
Cryptography
Slow Growing Bacteria
Reverse the Sequence
Cover the String
Dynamic LCA
Magic Bitwise AND Operation
Contaminated City
Code
ZZPERM
DELCOMM2
BOX
CRYPTO
SBACT
REVSEQ
MAIN8_E
DYNALCA
AND
CONTCITY
Accepted solutions
25
17
4
34
44
35
48
28
30
32
Problem name
Four Mines
Lost in Madrid
Circles
Bridges! More bridges!
Polynomial f(x) to Polynomial h(x)
Factorial Challenge
Hi6
Frequent Values
Code
MINES4
LIM
MINES4
BRII
MINES4
FUNFACT
HISIX
FREQUENT
Accepted solutions
5
11
9
9
10
10
8
11
The organizers would like to express their gratitude to everyone who participated in writing the
solutions.
38
Qualifications
For the purpose of designing a piping system it is desired to compute how much water is down from each
segment of the roof. To be prepared for a heavy November rain you should count one liter of rain water
falling on a meter of the horizontal plane during one second.
Write a program that:
computes the amount of water down in one second from each segment of the roof,
Input
The input begins with the integer t, the number of test cases. Then t test cases follow.
For each test case the first line of the input contains one integer (
being the number of
segments of the roof. Each of the next lines describes one segment of the roof and contains four integers
(
separated by single spaces. Integers
are respectively the horizontal position and the height of the left end of the segment. Integers
are respectively the horizontal position and the height of the right end of the segment. The
segments don't have common points and there are no horizontal segments. You can also assume that there
are at most 25 segments placed above any point on the ground level.
Output
For each test case the output consists of n lines. The -th line should contain the amount of water (in liters)
39
Qualifications
down from the -th segment of the roof in one second
Sample
input
1
6
13 7 15 6
3 8 7 7
1 7 5 6
5 5 9 3
6 3 8 2
9 6 12 8
output
2
4
2
11
0
3
Solution:
In this task we are asked to compute the amount of water that falls down from each segment of the roof.
First we want to calculate the amount of rain that is falling onto each segment directly from the sky above,
and then add the amount of all the water falling onto each segment from the lower end of some other one.
Notice that the coordinates are nonnegative integers less or equal then one million; this allows us to iterate
through all points on the ground level. While doing so we store the indexes of segments, which are located
somewhere above the current X coordinate on the ground, in a list (there will be at most 25 stored
segments at any moment during the iteration, as given in the task). So, for each step in this iteration we do
the following:
If a left end of a roof is encountered add it to the list. (we are doing this by moving one pointer in
the sorted list of roof segments by X coordinate of left end)
For each segment in the list whose lower end is equal to the current X coordinate determine the
segment under it which will collect the water falling from it. (this can be done by considering Y
coordinates of points located on the current segment and each one in the list, both with the
current X coordinate, in order to find the closest such point with lower Y coordinate than the point
on the current segment)
If a right end of a roof is encountered remove it from the list. (Pass through all list elements and
remove the one with right end equal to the current X coordinate)
Find the topmost segment from the current list and increase the rain counter for it by one. (similar
to the second step, we find the topmost point located on some segment from the list with the
current X coordinate)
Now the only thing left is adding the falling water from the segments above. Lets consider each roof as a
node and each connection between two segments (two segments are connected if water is falling from one
to another) as a directed edge with an end in the one above. We end up with a directed acyclic graph in
which for each node we need to compute the sum of all rain in the nodes reachable from it. This can be
simply done using depth first search, iterate through all nodes and if we dont have wanted information for
the current one calculate it by summing all rain collected in the child nodes recursively.
Solution by:
Name: Dimitrije Dimi
School: School of Computing, Belgrade
E-mail: dimke92@gmail.com
40
Qualifications
output
ambiguous
not ambiguous
ambiguous
Solution:
This was the easiest problem of all bubble cup qualification problems ever. You just need to make
inverse array from array A (defined as inverse[A[i]] = i for each i) and check if A[i] ==
inverse[i] for every i (1
i
N). Its easy to prove that its enough to check only that A[A[i]]
== i for every i (1
i
N, A[i]
i) so you can do this task with only one array and one loop
41
Qualifications
through the array.
The code for this task is really short, so we can run a shortest code competition . Here is my shortest code
in C, which passed all test cases on SPOJ.
n,i,b;
main() {
while(scanf("%d", &n), n) {
int a[n];
for(b=i=1; i<=n;) scanf("%d", a+i), b &= a[i] > i | a[a[i]]==i++;
puts("not ambiguous" + b*4);
}
return 0;
}
The length of this code is only 135 non-whitespace characters, and I want to thank all the guys who helped
me shortening it.
Solution by:
Name: Duan Zdravkovi
Organization: School of Computing, Belgrade.
E-mail: duxxud@gmail.com
42
Qualifications
where r is the number of faces required on the unspecified die, m is the number of sums of interest,
are these sums, and
are the counts of the desired number of different ways in which
to achieve each of the respective sums.
Input values will satisfy the following constraints:
, and
.
Values on the faces of all dice, both the specified ones and the unknown die, will be integers in the range
, and values for the s and s are all non-negative and are strictly less than the maximum value of
a 32-bit signed integer.
The last input set is followed by a line containing a single 0; it should not be processed.
Output
For each input set, output a single line containing either the phrase Final die face values are followed by
the r face values in non-descending order, or the phrase Impossible if no die can be found meeting the
specifications of the problem. If there are multiple dice which will solve the problem, choose the one
whose lowest face value is the smallest; if there is still a tie, choose the one whose second-lowest face
value is smallest, etc.
43
Qualifications
Sample
input
1
4
5
1
6
6
4
6
4
3
8
4
0
output
Final die face values are 1 1 1 2 6
Impossible
Final die face values are 3 7 9 9
1 10 15 20
5 2 3 3 1 11 3 16 4 26 1
1 2 3 4 5 6
3 7 6 2 1 13 1
1
1
3
1
4
2 3 4 5 6
2 2 3
7 9
4 5 9 23 24 30 38
48 57 51 37 56 31 63 11
Solution:
Maybe the first impression was that this task is a little bit confusing, but considering the constraints that
were given in the task it turns out that you only needed to find a way to see if it is possible to create the last
die so it fits the conditions, while keeping in mind the time complexity of your algorithm.
First we create a 2D matrix in which we will keep the number of ways in which you could get all sums
with
dice (there are given dice). In this matrix the rows would represent the number of dice, and
the columns would represent the numbers possible to get from the sum of the dice (e.g. if we had
that would mean that we could find 5 ways to achieve the sum 2 with the first four dice). We
would calculate fields in this matrix like this:
for every die (with an index j),
and for all its sides
[
] , where
Then, for the last die, when we need to find out if we can create it, we can try all possible values for its
sides using brute force. If we have two arrays (like and from the input for the last die) then we would
after performing the operation
(where is any index for the die side)
check if
is negative. If that is the case then we know that we can't make the last die in this way. In the
other case,
is a positive number and we would with a recursion try to find the value for the next side of
the last die. After the recursive call we would set back the value of c[j] so we can do another recursion in
the next iteration.
Next we would check if the combination is ok (just go through the given conditions and see if everything
fits).
After every recursion, if we found a combination of sides for the last die, we still need to check if the array
is empty. If it is, then we have a valid solution, and we are finished. If we went through all combinations
and didn't find a valid one then there is no solution.
Solution by:
Name: Uros Joksimovic, Milos Biljanovic, Dejan Pekter
School: School of Computing, Belgrade.
E-mail: uros.joksimovic92@gmail.com, miloshb92@hotmail.com, deximat@gmail.com
44
Qualifications
Input
The input consists of multiple datasets, each in the following format.
nm
row1
rown
is the number of rows which satisfies
. is the number of columns which satisfies
Each
is a sequence of m digits separated by a space. The digits mean the following.
0: Empty
1: Occupied by an obstacle
2: Marked with 2
3: Marked with 3
The end of the input is indicated with a line containing two zeros separated by a space.
Output
For each dataset, one line containing the minimum total length of the two lines should be output. If there is
45
Qualifications
no pair of lines satisfying the requirement, answer 0 instead.
Sample
input
5
0
0
2
1
0
2
2
0
6
2
0
0
1
0
0
0
5
0
0
0
0
0
3
2
3
5
0
3
0
1
0
0
0
0
0
2
1
0
0
3
0
1
0
0
0
0
1
3
0
0
0
0
0
3
0
0
0
0
0
0
output
18
2
17
0
3
0
0
0
1
0
2
Solution:
The approach for this problem is very straight-forward: let's try every possible placement of the line
connecting 2s and then look at the shortest available line between 3s and take the best result.
Of course, that solution is too slow and we need some optimizations to prune the search tree to fit the
time. Let's look at some situations which will surely lead to a suboptimal solution:
a) U-shape turns (see Figure 1) - if there are no obstacles, it can be easily replaced by a shorter
piece of wire. Note: This optimization is the most important one!
b) let's say that we are in field A and there is an adjacent field B that has been visited a long time
ago (meaning not in the previous step) - it's bad, because it would have been better to go straight from B to
A and avoid the loop see Figure 2.
46
Qualifications
c) suppose that we have constructed some part of the line between 2s. If at this moment there is
no path between 3s (we can check this easily using breadth-first search) we can stop searching, backtrack
and try some different way. It turns out that checking for such situations in every step is quite slow, but if
we do it on every 300th step, for example, it will considerably speed up our program.
We can also deduce some steps in the very beginning as long as there's only one possible movement from
any 2 or 3 - let's do it and mark it on the grid. It will always help our program.
Obviously, many more optimizations can be applied, but an efficient implementation of the
abovementioned ideas make our program easily fit the time limit.
Solution by:
Name: Bartek Dudek
Organization: XIV LO Wrocaw
E-mail: bardek.dudek@gmail.com
47
Qualifications
You can give John two types of orders (just print them to standard output):
Weighting spheres. All numbers should be separated with a space and they stand for: - number
of spheres that should be put on one of the scales (there should be the same amount of spheres on
both of the scales),
- identifiers of spheres that you want John to put on the left scale
and
- identifiers of spheres that you want John to put on the right scale.
After conducting the weighting John will tell you about the outcome (which you will be able to read
from the standard input). Possible answers are LEFT - spheres on the left scale are heavier, RIGHT spheres on the right answer are heavier, EQUAL - spheres on both scales have equal weight.
After conducting the weighting John is ready right away to execute the next order.
However, you should remember that if the weighting's number is too high John can become quite
bored...
Answering. This order is to give information that is the identifier of the searched sphere; however
if the sphere we are looking for is lighter than the other ones you should precede that with a '-'
sign.
John no longer needs you after that command (your program should end).
Output
Output the month number the accountant-robot will rust in. Months are numerated 1 to .
Sample
input / output
John:
You:
John:
You:
John:
You:
3
WEIGHT 1 1 2
LEFT
WEIGHT 1 1 3
EQUAL
ANSWER -2
Remark:
Program should clear the output buffer after printing each line. It can be done using fflush(stdout)
command or you can set the proper type of buffering at the beginning of the execution - setlinebuf(stdout).
48
Qualifications
Solution:
The problem is one of the variants of the Coin-Weighting problem: Given
coins, one of which is
counterfeit, and a pair of scales (two-pan balance) without weights, what is the minimum number of
weightings needed to find the counterfeit coin? There are variants in which we know/dont know if the
counterfeit is lighter/heavier, in which we are required to only indicate counterfeit/determine its weight, in
which we have/dont have some additional genuine coins etc. The following theorem gives us the required
minimum number of weightings for the corresponding variant of the problem and its constructive proof can
easily be implemented to obtain the required algorithm:
Theorem 1: Given coins, numbered from 1 through ,
of which are genuine and with exactly one
counterfeit among them, the minimum number of weightings needed to determine index of the counterfeit
.
and if its lighter or heavier than the others is
Proof: Let be the optimal number of weightings. Since we have candidates for counterfeit coin, and in
each case the counterfeit can be lighter or heavier than the genuine coin, there are
possible outcomes
in total. On the other hand, let us mark the result of each weighting with a number from set
;
-1 denotes that the left pan of the scales was heavier, 0 denotes that the scales were balanced and 1
denotes that the right pan was heavier. The arrangement of the coins on the scale pans on the -th
weighting depends only on the results of previous weightings and previous rearrangements, which were
themselves induced by the previous weighting results. Therefore, after the arrangement of the coins on the
scale pads for the first weighting is fixed, the subsequent rearrangements depend only on the results of
previous weightings (with if-then conditions for new rearrangements) and the final outcome (counterfeit
coin) depends only on the weighting results. It follows that the outcome of the weightings can be
uniquely described as a sequence
of individual weighting results
.
We just showed that weightings can distinguish between at most
different outcomes; since we must
be able to recognize
outcomes, it follows
. Since
is odd, we can rewrite the inequality as
(instead of the parity argument, we could also notice that weighting sequence
cannot tell whether the counterfeit is lighter or heavier because of that only
sequences are valid).
However, this inequality is a bit weak; we will improve it.
Let be the number of coins which will be put in the first weighing on each pan. If in the first weighting
the pans are balanced, the counterfeit coin is one of
coins not participating in this weighting. The
remaining
weightings must be enough to identify the counterfeit among
coins and to find
out if it is heavier or lighter. As before, it follows
(because of the parity argument).
However, if in the first weighting the pans arent balanced, the counterfeit is among
coins which
participated in this weighting. Unlike the previous case, this time it is enough to find only an index of a
counterfeit coin in the following
weightings; its weight can be determined from the first weighting.
Therefore, we are only interested in
outcomes (not
) and it follows
(parity
argument again). Adding
and doubled
results in
,
which is (using the fact that is an integer) equivalent to
We will now prove that this bound is achievable by explicitly constructing the weightings. It suffices to
construct the required
49
] (for
, less than
weightings are
Qualifications
needed). It is assumed that
since
coins.
(if
) or , if
coins, and we can apply the method recursively again. We will call this
each.
Now,
we
divide
each
group
into
subgroups
subgroups
have
coins each. In the first
weighting, we place group on the left pan and group on the right pan. Regardless of the result, in the
second weighting, we remove subgroup
from the left pan, move subgroup
from the right pan to
the left and put subgroup
to the right pan.
If the result of the second weighting differs from the first one
, then the counterfeit coin belongs
to some of the subgroups
; moreover, from these 2 weightings we can precisely deduce
which of the 3 subgroups contains the counterfeit and if the counterfeit is lighter/heavier than the
others. To see this, it suffices to consider all 6 possibilities (
vs.
vs.
and lighter vs. heavier)
they all give different weighting result sequence
After these 2 weightings, we have a group of
coins with counterfeit coin of known weight we can solve this using the simple method in
weightings, which gives weightings in total.
However, if the result of the second weighting remains the same
, it follows that all the coins
from the subgroups
are genuine. In that case, we repeat the same process as in the
second weighting, only this time with subgroups
If
, we use the simple method on
coins as in the previous paragraph, otherwise we rotate subgroups
etc.
This algorithm always uses weightings for identifying counterfeit and its weight: if counterfeit belongs to
one of the subgroups
, we will use one starting weighting,
subgroup rotations and
simple methods weightings weightings in total, as required.
What if
| |
; if
? Again, we divide
then | |
| |
; if
: if
then | |
then | |
| |
| |
| |
, we have
50
Qualifications
| |
Therefore, we can write | | | |
edge
case,
we
divide
each
| |
, where
. Now, just like in an
into
into
subgroups
subgroups
have
coins each, for
, and subgroups
have coins each. Since
, a simple method can handle this
subgroup with at most
weightings. Now, with the edge case algorithm, we are able to determine the
counterfeit coin in weightings.
group
However, note that the group might have fewer coins than the groups
. This is not a problem for
we can leave subgroups
and
one coin short | | | |
; if, during an algorithm, we reach
those subgroups, it means that all coins in subgroups
for
are genuine, and we can use them
to fill those 2 subgroups. For
, in particular for
and
, group division should be
and
, respectively (the only cases with | |
). This completes all steps of the algorithm.
With this, Theorem 1 is proved and the optimal weighting sequence is explicitly constructed.
Implementation:
Direct simulation of a mentioned algorithm with subgroup rotations and the simple method. Since
, we can traverse all the coins during each weighting with a total complexity of
Note:
The online judge system requires a sharp bond on weighting number for this task. If contestants code
exceeds the optimal number of weightings, John will not report the outcome of the weighting and TLE
(time limit exceeded) will occur.
Other variants of the Coin-Weighting problem and some different (and generalized) weighting
constructions can be found in [1].
References:
[1] Marcel Kolodziejczyk, Two-pan balance and generalized counterfeit coin problem
[2] http://www.cut-the-knot.org/blue/OddCoinProblems.shtml
[3] http://www.mathplayground.com/coinweighing.html
Solution by:
Name: Nikola Milosavljevi
School: Faculty of Mathematics, University of Ni
E-mail: nikola5000@gmail.com
51
Qualifications
100
7 8
4 6
20
2 3
1 2
5
2 2
1 2
2 2
2 3
1 2
output
FF
BB
IMPOSSIBLE
7 8
4 6
2 1
2 2
1 2
52
Qualifications
Solution:
At the first glance, this appears to be a problem requiring finding the shortest path. The issue is to find the
correct vertices. Obviously, keeping the index of the road is not enough, as there are two ends. Plus, you
need to keep track of whether you have traveled across that road or not.
Thus, define a new graph
, where each vertex is described by a triple
which uniquely identifies your current position:
-
The set of edges can be found quite easily. This is left for the readers as an exercise.
A sightseeing tour now becomes a path from the vertex
or false).
to itself. (
can be true
is dependent on
depends solely on
The DP solution shares the same idea as the first solution. The recursion is not difficult and is performed by
calculating in the following order:
As any state is visited exactly once, the time complexity of the algorithm should be
Solution by:
Name: Linh Nguyen
School: Vietnam National University
E-mail: ll931110@yahoo.com
53
Qualifications
Your aim is to maximize the sum of all the numbers in the resulting sequence by applying appropriate
segment flip operations meeting these constraints.
For instance, suppose the sequence is
and you are allowed a single segment flip. The best sum
you can achieve is , by flipping all numbers as a single segment to
.
Input
The first line contains
.
integers
and
Output
A single integer denoting the maximum possible sum of the final array.
Constraints
Sample
input
3 1
-5 2 -3
output
6
Solution:
This interesting problem was definitely one of the hardest ones on Round 1, and the fact it had the lowest
amount of correct solutions out of all the problems of the round confirms that. The main idea is not very
hard to conceive but implementing it correctly can get a bit frustrating.
The problem statement sticks to formal mathematics and hence doesnt require any particular decoding:
we are asked to determine the maximal sum of a sequence of integers after performing no more than K
segment flip operations on disjoint segments (where one operation negates an entire range of the
sequence). This problem is not extensively covered in literature, however there exists one paper which
names this kind of problem the Maximal-Scoring Segment K-Set problem. It is a problem that arises
commonly in bioinformatics, most notably DNA and RNA analysis.
Before implementing the main algorithm, its wise to first transform the given sequence into a more special
case, which is equivalent to the initial sequence but will make our calculations simpler. First of all, it is fairly
54
Qualifications
easy to notice that if there are positive integers on the ends of the sequence, they certainly wont need to
be flipped, hence we can immediately exclude them from the range were observing and add them to the
final solution. That way were left with negatives on both ends of the observed range, and this is a property
we can constantly maintain as we build our set of segments; it will later be clarified how. The next
transformation we can immediately apply is to compress successive runs of positive/negative integers
into a single integer with the value of the sum of all integers in that run. Why can we do this? Lets say a
negative integer is contained in the final set of flipped segments; it is obvious that including all the
negatives adjacent to it can only benefit to the solution. Analogously, the only reason why we would want
to flip a positive integer is to join together two segments of negatives, and we cant do this if we dont flip
all the other positives in that run as well. In the end we are left with an alternating sequence of negative
and positive integers. For visualization, refer to Fig. 1.
Lets say that after the given transformations are applied, there are exactly M negative integers in the
sequence. What is the maximal sum we can obtain with M segment flips? It is obviously the sum obtained
when we flip all the negatives separately. If
, then this is also the optimal solution to the problem.
Otherwise, the solution is derived from the M-segment solution using a theorem that is formally stated
in [1], albeit with its proof omitted. It states that a solution for
segment flips can be obtained from
the solution for segment flips by either merging two segment flips or excluding one. Using this we can
find the solution for segment flips in
iterations.
It is easy to conclude that the segment to be excluded/merged through in any iteration must be the
segment with the minimal absolute value (its removal/flipping would pose minimal damage to the sum
obtained with M flips), so we are required to store segments we are observing in a structure which will
efficiently provide this segment; one of the possible data structures we can use for this is a min-heap.
Now lets discuss the algorithm itself; in every iteration, the algorithm extracts the segment with the
currently minimal absolute value from the heap. In the case that this segment is on one of the ends of the
currently observed range, we know that we have run into a negative segment and that we will never have
to re-include it again; hence, it is optimal to remove both it and the positive run adjacent to it from
consideration, so we are left with a negative segment at both ends again. If the extracted segment is not at
either end, the action taken depends on the sign of the segment:
- If the segment is positive, we flip it to merge the two negative segments adjacent to it;
- If the segment is negative, we exclude it for now; it is possible to re-include it, but only together with
both positive segments adjacent to it.
If we look at this a little closer, we can conclude that same actions can be performed regardless of the
sign: subtract the segments absolute value from the optimal solution obtained in the previous
55
Qualifications
iteration, remove the segment and its two adjacent segments from the heap and insert a segment which is
obtained by merging those three. With a little optimization to assign an ID to each segment, and to
constantly store the IDs of segments directly to the left and right of them, the updates described above can
be done quite efficiently. This concludes the algorithm description, and it turns out to be fairly short and
easy to code (requiring only ~50 lines of code for the main algorithm).
The time complexity of each iteration of the algorithm is
for updating the heap, hence the overall
asymptotic time complexity of this solution is
. The memory complexity of the solution is
.
For a more in-depth look at the Maximal-Scoring Segment K-Set problem, its generalizations, as well as
formal statements of the theorem and algorithm mentioned here and the algorithms application in
analyzing biomolecules, refer to [1].
References:
[1] Mikls Csrs: Algorithms for Finding Maximal-Scoring Segment Sets (extended abstract), IEEE/ACM
Transactions on Computational Biology and Bioinformatics (2004)
Solution by:
Name: Petar Velikovi
School: Matematika Gimnazija
E-mail: petrovy.velickovic@gmail.com
56
Qualifications
can be done by removing bricks from a building or adding some bricks to a building.Removing a brick or
adding a brick is done at certain cost which will be given along with the heights of the buildings.Find the
minimal cost at which you can make the buildings look beautiful by re-constructing the buildings such that
the
buildings satisfy
( can be any number).
For convenience, all buildings are considered to be vertical piles of bricks, which are of same dimensions.
Input
The first line of input contains an integer which denotes number of test cases .This will be followed by
lines , 3 lines per test case. The first line of each test case contains an integer n and the second line
contains n integers which denotes the heights of the buildings
and the third line contains
n integers
which denotes the cost of adding or removing one unit of brick from the
corresponding building.
Output
The output must contain
Sample
input
1
3
1 2 3
10 100 1000
output
120
Solution:
First, let
be the height of the shortest building, and let
be the height of the tallest building. It isn't
hard to notice that the solution will satisfy the inequality
. This is easy to prove - if
there is a solution smaller than low, then we need to remove bricks from every single building. The
solution is guaranteed not to be optimal because removing a brick from each building will cost less. The
proof of the latter,
, is analogous.
Since the limitations for heights for this problem are quite low, the following algorithm with time
complexity
solves the problem.
|
| . Let
be the cost of changing the height of the i-th building to . Clearly,
be equal to
. Clearly, the total cost to change the heights of all buildings to k will be
.
Now we define
. Similarly, we define
. Notice that this
is also equal to
The reason why we are doing this is because we want to be able to
Let
57
Qualifications
quickly calculate
if we know
and
, for some x. We can calculate
in
, but, how
can we calculate
for some x? Since
for
and otherwise (in other words, it
decreases by
every time we increase the target height if it's smaller than the original height, and
increases otherwise), we can calculate
from its definition as
. This leads to an
algorithm, which is still too slow.
So, let's revisit the above procedure. Define
as
. Notice that
for
time and
space.
Solution by:
Name: Ivan Stoi
School: Gymnasium Svetozar Markovi, Ni
E-mail: ivan100sic@gmail.com
58
Qualifications
Output
For each test case output one line giving the final sum for each test case.
Sample
input
1
5
1 5 3 6 4
output
15
Solution:
All you needed to do to solve this task is to sum up for every given number all past numbers which are
smaller than that number. Sounds simple enough.
So a naive solution would be that you have an array of numbers so that every given number is added in
time to that array, and after that the required sum can be computed in
time. This algorithm is
slow given the constraints (there can be
numbers per test case) so we need to think of another way to
implement these two operations.
This can be solved by cumulative tables, where cumulative stands for how much so far and that is what
we need. The time complexity for add and sum operations are
, which is fast enough to pass.
The whole idea behind the cumulative tables is if we can represent a number in a binary notation (e.g .
or 1110 in binary) , then we can also represent any sum of numbers as a sum of
specific subtotals.
For an example if we need the sum of numbers that are less than 14, then we would have a dynamic array
where we would keep our subtotals, so for that sum we would only need to look at a few subtotals to get
the result, which can be done in
. Why is the complexity logarithmic? The binary presentation of 14
is 1110, so to get the subtotals, we would delete the rightmost one in binary and with that new number we
would use it as index to get the subtotal from the dynamic array. We would repeat the process until we
59
Qualifications
delete all ones (get zero as index) and along the way sum up all the subtotals. There are about
operations to execute because there can be at most
digits in the binary representation of .
For adding an element to our dynamic array, so the subtotals that we have are correct, we will do the
opposite of what we were doing when we were getting the required sum. We only need to update
subtotals that depend on the number we are adding so to speak, so there are at most
subtotals that
need to be updated, so the time complexity for adding is
too.
Solution by:
Name: Uros Joksimovic, Milos Biljanovic, Dejan Pekter
School: Racunarski fakultet (RAF)
E-mail: uros.joksimovic92@gmail.com, miloshb92@hotmail.com, deximat@gmail.com
60
Qualifications
and labels are also numbers. All numbers in the input are nonnegative
Output
Print "YES" if there are two distinct walks with the same labelling from node 0 to node 1, otherwise print
"NO".
Sample
input
4 4
0 2 0
0 3 0
2 1 1
3 1 2
10 9
0 2 0
2 1 0
2 3 0
3 4 0
4 2 0
2 5 0
5 6 0
6 7 0
7 8 0
8 2 0
output
NO
YES
Solution:
The problem statement is very brief, but there is a lot of information hidden among the test cases. Lets
first dissect what we should do. We are given a directed labeled multigraph and we need to find out if
there are at least two distinct paths from node 0 to node 1, such that we can only traverse edges with the
same labeling. The previous sentence needs some explanations: when you traverse edges finding requested
paths you need to have the same sequence of edge labelling, e.g. if you have a path that contains edges
with labeling 1-5-10-10, the other path also must have 1-5-10-10 labeling of its edges. The distinction
criteria is based on the visited nodes, so in the above example if we did have two paths with same labeling
but at least one node differs, we do have two distinct paths and the answer is YES.
So now that we understand what we should do, lets talk about possible solutions.
Lets consider a nave solution first. Let us find all the paths, select pairs of paths that have the same
labeling and check if there is a difference in visited nodes. As you may guess this is way too slow, it has
exponential time of execution and for 2000 nodes/edges it wouldnt produce a solution even if we had
1000 years of spare time.
We need to abstract things a bit so that we can prune paths that we dont need.
61
Qualifications
The question is: Do we even need whole paths?
The answer is: No, well after thinking a bit on this problem you would probably come to the same kind of
abstraction. The key point here is to search for distinct paths in parallel. Lets consider that we have two
paths, but we dont really need all the information: what nodes path contain, what edges path contains,
and so on... We only need to know what are the nodes of path at some point, and if the paths contained
different nodes at some point. Lets define state in two paths after traversing N edges as:
This state can be described as three-parameter function f(node, node, bool), where we have
which is about 8 million at most.
states,
So what you need to do is perform a breadth-first search (or an iterative depth-first search, because
recursive DFS will fail due to stack overflow when it tries to call itself several million times) which is going to
traverse graph in parallel. So the BFS should look like this:
parallel_bfs(0, 0, false)
queue.add(state(0, 0, false));
state = getStateFromQueue();
for every pair of state.node1s and state.node2s neighbor whose edges have same labeling
if ( state (node1, node2, distinct || (node1 != node2) is not visited)
mark state as visited
put that state in the queue
62
Qualifications
output
j
1
bac
cab
4
abaca
acaba
2
1
babacbcabacabadabababababababababadab
213216
Solution:
The first thing you should notice about the problem is that there are at most only |
|
distinct letters in the word W. After that, let's first focus our efforts on solving the first part of the
problem: counting the number of zig-zag permutations of .
The solution will be an application of dynamic programming. Let's say we constructed the first
63
characters
Qualifications
of a specific zig-zag permutation and we need to construct
more of them. The only things we need
to know are: what's the last ( -th) character, whether the next character should be greater or lesser then
the -th, and how many characters of which kind are remaining. Given that data, we can count the number
of ways we can extend the word to form a complete zig-zag permutation.
For example, let's say we constructed the prefix and the state is now
We can obviously transition from that state to
and
.
Associating the number of zig-zag permutations with the state enables us to calculate the first required
number. The only thing left to do is to pick the first character and the relationship between the first two
characters and sum up the numbers for each choice.
From a complexity point of view, the solution isn't perfect. If the original word
had 6 occurences of each
of the 10 letters, then the number of states would be
, because there are 10 possibilities for
the last character, 2 possible directions and every character can occur from 0 to 6 times, yielding a total of
states. The said number is about
and is generally too big to handle within the time limit. Luckily,
no such test cases exist and the said algorithm is good enough to run within the allowed time.
As for the second part of the problem (finding the -th zig-zag permutation), it's amazingly simple to
implement after we know how to solve the first part via dynamic programming. You can easily find the first
character of the string by counting how many permutations there are with a certain first character and
stopping when the cumulative number exceeds . A similar algorithm can be used to find the second
character, etc. Such an algorithm is sufficient to solve the problem.
Solution by:
Name: Goran ui
School: FER, Zagreb
E-mail: zuza777@gmail.com
64
Qualifications
output
2
2
BP +
BPC +
TURBO EXCHANGE +
EXT +
HARDWARE +
MOUSE
NETWORK
For the two tests above,the corresponding DEL commands are DEL BP* and DEL EX*.
Solution:
This problem requires of us to find a wildcard pattern which matches the largest amount of files, but not
any of the files which are marked as need to be saved. It means that we can create a list for each file,
containing all patterns which match it. Then we just need to find the pattern which is contained in the
65
Qualifications
maximal number of safe lists, but in none of the unsafe ones.
The first problem with this idea is that the list of patterns can get really big, so we have to leave out some
of them. Lets see which patterns can be safely left out. For example, if a pattern contains ** its
equivalent to the pattern where one of the * is left out. Further, a pattern such as ?*?*? is equivalent
to ???***, which is then equivalent to ???*. Generalizing this insight, we conclude that we dont have
to look at any patterns containing consecutive *s or a ? immediately following a *. This gives us a
more manageable list for example, a file named AB is matched by the following list of wildcard
patterns:
??
??*
?B
?B*
?*B
?*B*
?*
A?
A?*
AB
AB*
A*B
A*B*
A*
*A?
*A?*
*AB
*AB*
*A*B
*A*B*
*A*
*B
*B*
*
It can be calculated that the worst case is when we have a file name containing 8 different characters, and
that for this case, taking into account that the maximum allowed length of a pattern is 8 characters as well,
the pattern list contains somewhere around 8000 elements.
To find a pattern which is contained in the maximal number of lists, we will make use of the trie data
structure. Each pattern from each list is added to the trie, and we add 1 to the value of the node in the trie
if the pattern was pulled out from a list corresponding to a file which can be deleted, and a
is added if the list was for a file that is not allowed to be deleted. we
value
In the end we just have to go through the trie and find the node with the maximal value.
The time complexity of inserting a pattern to the trie is
, which gives us the total
time complexity
(where
denotes the number of files (
)
and
the maximal number of wildcard patterns for some file (
, as discussed)). The memory
complexity has the same order as the number of nodes in the trie, so some care has to be taken not to
allocate any unnecessary memory.
Solution by:
Name: Duan Zdravkovi
School: Raunarski fakultet (RAF)
E-mail: duxxud@gmail.com
66
Qualifications
The first line contains one positive integer n - the number of boxes
The second line contains n nonnegative integer separated by single spaces. The i-th number is the
number of balls in the i-th box.
Output
For each test case, output one nonnegative integer - the number of moves necessary to displace the balls in
such a way that in each box there remains no more than one ball.
Sample
input
output
1
12
0 0 2 4 3 1 0 0 0 0 0 1
19
Note
There are two input files. In the first input file, t=19, n<=1000, time limit=0.5 second; In the second input
file, t=3, n<=200000, time limit=15 seconds.
Solution:
In order to solve the problem above, we will first reformulate it.
We number the boxes in a clockwise order from 1 to , beginning from an arbitrary box. Let
denote
the box in which ball number was placed at the beginning. We number the balls so that
. Then we stretch the boxes
into a line and add infinitely many boxes before and after the line
(they are numbered
67
and
respectively).
Qualifications
We displace the balls so that at most one ball remains in each box. The new position of each ball will be
denoted b0(i). We will call b0(i) for
a solution for balls
. Furthermore, a solution will be
|
| is minimal.
called optimal if its cost
We will call the distance between the first and the last occupied box in a given solution (i.e. the number of
the boxes between them plus 1) span. We want to find the optimal solution for balls 1,...,m with span at
most
.
Before we do that, we will define an operation and introduce four lemmas.
We define an operation push left on a given solution. We take the rightmost ball and move it one box to
the left. If the box is not empty, we take the ball from it and again move one box to the left. We continue
this process until a ball is inserted into an empty box. In other words, we move the rightmost continuous
block of balls one box to the left. This operation changes the cost of the solution by . If
is a negative
number, than the solution is improved. Push right is defined in an analogous way.
(1).
that
and
,|
| |
|
|
|
|
Lemma 2 When we perform subsequent push left operations, each time the change of the cost
greater or equal than the change last time. (The same holds for the push right operation.)
is
Let us assume that in the rightmost continuous block of balls there are balls such that
,
and balls such that
. The push left operation changes the cost of the solution by
68
Qualifications
After the operation can increase or stay the same and
proves the lemma.
Lemma 3 Let us consider all solutions such that boxes with indices greater than are empty. We choose the
optimal one among them and call it . Now we want to find the optimal solution among all solutions in
which boxes with indices greater than
are empty. If box number was free in solution A, then we
may take
. Else we may obtain by performing push left on . This follows from Lemmas 1 and 2.
Lemma 4 If is the leftmost occupied box and is the rightmost occupied box in an optimal solution with
span
, then there exists an optimal solution with span
such that all occupied boxes are either
in range
or
.
Lemma 4 will be left without a proof. It can be proven by contradiction, when we consider rightmost
continuous blocks of balls in both solutions and estimate their lengths.
Algorithm
We may use these lemmas to construct the algorithm.
1. Firstly, we want to find an optimal solution with any span. We keep in memory an optimal solution
is free we set
If
is occupied, then we place the ball number to the right of the rightmost ball in the previous
solution. We perform push left as long as it decreases the cost of the solution. According to Lemma
3 this leads to an optimal solution.
2. After adding all
Implementation
Let us assign the same colour to balls which were in the same box at the beginning (which have the same
). Balls in the same colour form one continuous block in the solution produced by the algorithm this
is an observation based on Lemma 1 and the workflow of the algorithm. The block of balls of the same
colour (from the same box) will be called simply a colour. Each colour in the solution may be characterized
by three parameters:
its leftmost ball,
its rightmost ball and
the primary position
(box) of all the balls in that colour. Instead of considering single balls, we will consider colours. The figure
below shows an example of an initial and final placement of the balls.
Furthermore, we will create a structure which will store information about continuous blocks of balls in the
69
Qualifications
solution. We will call them large blocks. Large blocks consist of one or more colours.
),
),
).
When we perform the operation push left, we move the rightmost large block one box to the left. It may
make the colours in the large block change their groups (
).
If there is only a one-box distance between the rightmost and the second rightmost large block, than after
push left we have to merge these two into one large block. In order to make the algorithm sufficiently
fast, we have to concentrate on performing push left, updating the current cost of the solution and
merging large blocks.
When we perform push left, we have to change the cost of the solution by
To update the cost of the solution in a fast way, we remember the sum of the lengths of the colours in in
. Thanks to that, we calculate this part of
in constant time. We calculate the change of the cost for
each colour in separately. This is performed in amortized constant time, because each colour may be
pushed left at most
(its length) times when it is in group , then it will travel left to its primary
position and end up in group . The sum of the lengths of all colours equals .
For each large block, we may store information about colours from L and R in binary search trees (e.g. set
from the C++ STL) and colours from the group M in a dynamic array (e.g. vector from the C++ STL). The
colours in the BST structures are ordered by the number of remaining push left operations which will
make them change their group. If this number for the minimal colour in is equal to the number of
70
Qualifications
operations performed, than that colour is deleted from and added to . Colours in
are updated
separately after each push left, they are added to when they leave . Colours in cannot change their
group any more after push left. However, it is useful to store information about them in a BST we use
it to construct a similar data structure to enable the push right operation in the second part of the
algorithm.
The last thing that remains to be done is merging two large blocks. When we merge two groups of the same
kind, we always add elements from a smaller container to a larger one. Thanks to this, every element will
be inserted at most
times. The most time-consuming operation in the algorithm is merging binary
search trees, which in total takes
time (insertion of a single element into a BST takes
time).
Solution by:
Name: Bartosz Tarnawski
School: Szramek High School Katowice
E-mail: bartek.tarnawski@gmail.com
71
Qualifications
Solution:
This task is a bit different from the others, since we are given an encrypted problem statement. Therefore,
to solve the task, we need to decipher the statement. This also happens to be the main and interesting part
of this problem, since the task itself is rather easy (except for some ambiguity in the real statement).
In the introduction to the task statement, we are provided with some important facts we are dealing with
lowercase Latin letters, the language is English and, the most important fact, the method of encryption is a
form of substitution cipher.
One of the simplest and most commonly used methods for breaking the substitution cipher is frequency
analysis. This method, coupled with some manual tweaking, is enough to decipher the task statement. It
consists of counting the number of occurences of each letter in the ciphertext analysis of the frequency of
each letter in the ciphertext. Then, the more frequent letters in the ciphertext are mapped to the more
frequent letters in the English alphabet, while the less frequent are mapped to the less frequent letters in
the English alphabet. For this, we will, of course, need relative frequencies of letters in the English alphabet.
Then, in the best case, the most frequent letter in our ciphertext will map to the letter e (the most
frequent letter in English language), the second most frequent letter will map to the letter t and so on... Of
course, the process of decryption would be too easy then, so this is not the best case and we will have to
do some guessing. We can start by mapping the most frequent letters in the given text to the most
frequent letters in the alphabet, and then build it up from there by looking at the text we are getting when
applying our partial key, mixing the mappings a little bit, trying to get meaningful words and parts of words.
We can also use the frequency analysis of bigrams (two adjacent letters in the string) or trigrams. For
example, the most frequent trigram in the given text is nte, and it maps to the most frequent trigram in
the English language the. Slowly, by correctly guessing the parts of the needed key (permutation), we will
be getting more and more meaningful words, ultimately leading to this (spaces and punctuation included
additionally to show the real beauty of the statement):
I have told you that this problem is very easy, just like the problem life the universe and everything.
Yes, it's very easy, but you will have some trouble to get accepted if you don't care with the problem
description.
A very easy problem is not always a very boring problem.
72
Qualifications
Sometimes it will be interesting from the time you try it to the time you solve it because after lots of WA/TLE
you will feel very well.
The sun is shining outside the window. The birds are singing in the tree. The nature is harmonious.
What's the first problem of an online judge?
It's A plus B problem in common except sphere online judge.
This problem will be the first problem of most of the online judges.
The data limitations are multiple test cases.
All the numbers are separated by some whitespaces. A and B are integers and less than MAX_LONG_INT in
C or C++ language.
The input file will less than four megabytes.
I hope you can solve it as fast as possible because it's very very easy and the test cases are very weak. But if
you got WA/TLE you will work for a long time to find the mistake of your program possibly.
Enjoy this problem
Alright, the text may not be so beautiful at the end, and actually, it does not describe the problem very
well. Most of the people probably felt excitement and relief after successfully deciphering the text, but it
was only the beginning of a bumpy road to Accepted. The task is to print the sum of two numbers, but the
format of the input (and output) is still unknown, and the constraints are vague. Therefore, the method of
trial and error would have to continue to find out all the tricks that are hidden in this task. The first, and the
easier problem is to find out how the input looks like. By testing different solutions, it turns out that the
input consists of an array of 2N integers (there is no number in the input that tells us the value of N). Let V
be the given array. You have to print exactly N integers (separated by some whitespace), where each
integer represents the value of expression V[2i-1]+V[2i], for each i=1,,N. The second and more tricky part
of solving this problem is figuring out the constraints. It is stated that all the integers will be less than
MAX_LONG_INT. A lot of people initially assumed that their absolute value is less than MAX_LONG_INT.
But, it is a very wrong assumption, and, as it turns out, there is no lower bound on the value of numbers,
other than the size of the input file. Therefore, big integer arithmetics has to be used to solve the task.
Since the only operation is addition (and subtraction in case of two numbers with different signs), the
implementation is straightforward. Time limit should not be an issue in this task, since the time complexity
of the solution is linear, but reading the input should be done with care.
Solution by:
Name: Vanja Petrovi Tankovi
School: School of Computing, Belgrade
E-mail: vpetrovictankovic@gmail.com
73
Qualifications
output
3
5
0
3
0
15
0
0
5
Solution:
Given an
array of integers called and an integer , find the first moment when the sum of the
elements in the array is greater or equal to a given integer . Each second we apply the rule: if the value in
the cell
or its neighbours is greater or equal to , increase it by one.
Basic idea:
The first thing to notice is that the constraints on are relatively small , while and can be huge. So the
complexity of the solution must not depend on and much (maybe logarithmically proportional, but not
more).
There are two basic ideas on similar problems do a binary search on the answer or just simulate the
process. The binary search doesnt seem to be a good idea because when we fix the answer, there is no
easy way (at least I couldn't find one) to check if the answer is achievable (the only thing which comes to
mind is again simulation). So, our next stop is to think whether simple simulation is possible within the
74
Qualifications
constraints.
With up to 100 we can easily simulate each step, but the problem is that we may need to simulate billions
of steps. But, many of them will do the same thing in fact we will have only
steps in which
something changes. Really, the only change occurs when the value of a cell becomes greater or equal to
(because it activates its neighbours), and this can happen at most once per cell. This idea must be enough
to solve the problem!
So, we are ready with the basis of the solution group the steps and use a single iteration to simulate the
whole group.
Implementation:
There are different ways to implement the above idea with complexities ranging from
, and maybe even better. I will explain the
solution I used.
to
75
Qualifications
output
2 3 5
1 2 4
2 3 5
76
Qualifications
10 , 9 , 6 , 5 , 4 , 3 , 8 , 7 , 2 , 1
=>
10 , 5 , 4 , 3 , 8 , 9 , 6 , 7 , 2 , 1
We repeat this procedure - the lengths of the sequences to be taken are not changed, and the index of the
number from the beginning of the first sequence is decreased by 1 until we run out of indices. That means
this phase takes N/2 - 2 steps.
10 , 5 , 4 , 3 , 8 , 9 , 6 , 7 , 2 , 1
=>
4 , 3 , 8 , 9 , 10 , 5 , 6 , 7 , 2 , 1
After these steps the sequence will, in general, look like this:
4 , 3 , N/2 + 3 , N/2 + 4 , N/2 + 5 , ... , N , 5 , 6 , 7 , ... , N/2 + 2 , 2 , 1
For N=10: 4 , 3 , 8 , 9 , 10 , 5 , 6 , 7 , 2 , 1
Phase 2
Now we are just three steps away from reversing the sequence!
First, swap the sequences [2, N/2] and [N/2 + 1 , N] :
4 , 3 , 8 , 9 , 10 , 5 , 6 , 7 , 2 , 1
=>
4 , 5 , 6 , 7 , 2 , 1 , 3 , 8 , 9 , 10
=>
2 , 1 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10
Now swap the first two numbers, and you're done! The first phase takes N/2 - 2 steps, and the second
phase takes 3 steps, for a total of N/2 + 1 steps.
Odd N
The general idea for odd N is the same as for even N. In phase 1, we start reversing sequences of lengths 2
and (N+1)/2 from the index (N-1)/2 - 1. This takes (N-1)/2 - 1 steps, that is, N div 2 - 1 steps. The sequence
will look like this after phase 1:
3 , 2 , (N-1)/2 + 3 , (N-1)/2 + 4 , ... , N , 4 , 5 , 6 , 7 , ... , (N-1)/2 + 2 , 1
The phase two, however, takes just two steps - swap [2 , (N+1)/2] and [(N+1)/2 + 1 , N] and [1 , (N-1) / 2]
and [(N+1)/2 , (N+1)/2 + 1].
Demonstration of phase 2 for N=11:
3 , 2 , 8 , 9 , 10 , 11 , 4 , 5 , 6 , 7 , 1
=>
3 , 4 , 5 , 6 , 7 , 1 , 2 , 8 , 9 , 10 , 11
3 , 4 , 5 , 6 , 7 , 1 , 2 , 8 , 9 , 10 , 11
=>
1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 , 10 , 11
The phase 1 takes (N-1)/2 - 1 steps, and phase two takes 2 steps, for a total of N div 2 + 1 steps.
Small N
For N=3 and N=4, phase 1 is omitted. For N=2, we just swap those two numbers.
Conclusion
The implementation of the algorithm is easy, although reaching it is far more difficult. The complexity of
the program itself is O(N) - it doesn't compute anything, just prints some predetermined numbers.
Solution by:
Name: Ivan Stoi
School: Gymnasium Svetozar Markovi, Ni
E-mail: ivan100sic@gmail.com
77
Qualifications
Given two strings A and B. You have to find the length of the smallest substring of A, such that B is the
subsequence of this substing.
Formally speaking: you have to find the length of smallest possible string S such that
S is the substring of A
B is the subsequence S
Note: Subsequence of an string S is obtained by deleting some (possibly none) of the characters from it. for
example "ah" is the subsequence of "aohol"
Input
First line contains T, the number of test cases. Then T test cases follow, 2 lines for each test case, 1st
contains A and 2nd contain B.
|A|<=20000, |B|<=100
Output
For each test case print the answer in a new line. if no such substring exists print -1 instead.
Sample
input
2
aaddddcckhssdd
acs
ghkkhllhjkhthkjjht
hh
output
10
3
Solution:
Since we are looking for the smallest possible string it is quite obvious that will start with the first
character of string and end with the last character of string . Let all strings be zero-indexed and let be
equal to | | and be equal to | |. We will try to build the solution from any occurrence of character
]
in string . Observe that there is no point in skipping characters of string B in string A.
For example, lets say that string is equal to
and string is equal to
. The solution
will of course be
and not
, so we conclude that we need to use some kind of a greedy
algorithm to solve this task. The main idea of the algorithm is that after we have string , which is a
substring of string and has first
characters of string as its subsequence, we try to build string
which will be a substring of string and will have first
characters of string as its subsequence and
string will be prefix of string
.
So how do we do that?
We can expand string to string
string until we reach character
From all strings
78
Qualifications
Now we just need to find some quick way to expand any string to string
. We will need some matrix
and
will tell us the position of the first occurrence of -th character of the alphabet
(
) after position in string .
How to build matrix
Build matrix
Try to build string
starting from any occurrence of character
Use matrix
to expand any string to
in string
Solution by:
Name: Aleksandar Ivanovi
School: Prva kragujevaka gimnazija
E-mail: aleksandar.ivanovic.94@gmail.com
79
Qualifications
link A B : add an edge from vertex A to B, making A a child of B, where initially A is a root vertex, A
and B are in different trees.
cut A : remove edge from A to its parent, where initially A is a non-root vertex.
lca A B : print the lowest common ancestor of A and B, where A and B are in the same tree.
Input
The first line of input contains the number of initial single-vertex trees N and the number of queries M (1
M 100,000). The following M lines contain queries.
Output
For each lca query output the lowest common ancestor (vertex number between 1 and N)
Sample
input
5 9
lca 1 1
link 1 2
link 3 2
link 4 3
lca 1 4
lca 3 4
cut 4
link 5 3
lca 1 5
output
1
2
3
2
Solution:
First of all, if there were no "cut" and "link" operations, and all nodes were connected, how would we solve
the problem? One of the methods to find LCA is this: create an empty array and make a DFS order of the
tree. As we traverse edges (either forwards or backwards), whenever we enter a node, append that node to
the end of the array. This array will contain
elements in the end. Note that this does not mean each
node appears twice in the array! Now to find LCA of nodes A and B, pick any of their occurrences in the
array and find the node with minimal depth between them. This can be done in
using any rangeminimum-query (RMQ) data structure.
Let's see what happens to the array containing nodes in DFS order on operation "cut": if we cut node A, the
interval beginning from the first occurrence of node A and ending at the last occurrence of node A is being
cut from the array and becomes a new array. What about operation "link A B"? The array starting and
ending with node A is plugged in the array containing node B between two consecutive B's. Note that
cutting and linking may require slight modifications like duplicating a node or removing a duplicate to fix
80
Qualifications
the DFS order.
The last obstacle to solving this problem is making all operations fast. There's an awesome data structure
called the splay tree. Using splay trees we can easily cut and paste intervals and query for minimum in an
interval. The idea is to just naively implement operations, and make sure that we splay any node we were
looking for by traversing any tree from the root. This magically gives
per operation.
Solution by:
Name: Stjepan Glavina
School: FER Zagreb
E-mail: stjepang@gmail.com
81
Qualifications
output
Case #1: 4
Case #2: 9
Solution:
For solving this task we will require some basic knowledge of binary numbers and bitwise operations. The
solution for this task is some kind of a pruning search. We will use the most basic recursion for finding all
the -combinations of elements and use some optimizations to make it faster. Observe that for all
numbers and
the following inequality holds:
, where represents the bitwise AND
operation. So first of all, we will sort the numbers in non-decreasing order. We set the initial solution to be
some very large number (for the limits in this task
will suffice). We use the following optimizations:
if we select exactly numbers or we reach the end of the array we dont go any further in the recursion.
Also, since we concluded that including larger numbers in the combination will make that combination less
or equal to the previous one, we can check if including all the numbers after the current position will give
us some number that is greater or equal to the solution and if that is the case we dont go further in the
recursion either. For that optimization we will need to use some preprocessed array
, where
is
equal to
(all arrays are zero-indexed). We can preprocess array
in
either linear or quadratic complexity, it doesnt affect the total time that much. One more optimization is to
check in every step if the current combination is smaller than the best solution so far and update the
solution if that is the case. Using all of the above optimizations will be enough to solve the task within the
82
Qualifications
given time limit. The recursion itself is very simple to code and very short. The implementation follows:
void Solve ( int idx, int Cnt, lld Curr )
{
if ( Curr < Sol ) Sol = Curr;
if ( ( Cnt == K ) || ( idx == N ) ) return;
if ( ( Curr & DP[idx] ) >= Sol ) return;
Solve ( idx + 1, Cnt + 1, Curr & A[idx] );
Solve ( idx + 1, Cnt, Curr );
}
(
represents the current position in the array,
represents the quantity of numbers that we take in
the combination and
represents the value of the combination.)
Solution by:
Name: Aleksandar Ivanovi
School: Prva kragujevaka gimnazija
E-mail: aleksandar.ivanovic.94@gmail.com
83
Qualifications
Output
For each test case there is one line in output. If all people can be rescued "All people can be rescued in D
day(s) ." should be printed, where D is the minimum number of days to rescue all people. If it is impossible
to rescue all people "X survivor(s) can be rescued." should be printed, where X is the maximum number of
survivors that can be rescued.
84
Qualifications
Sample
input
2
4
3
4
5
6
1
2
3
4
4
6
5
3
4
2
2
3
1
1
2
2
3
3
4 4
2
3
4
1
4
3
2
1
2
7
3
3
4
7
2
3
6
3
4
3
4
2
3
3
3
2
4
2
output
All people can be rescued in 6 day(s).
7 survivor(s) can be rescued.
Solution:
Lets reformulate this task in graph theory. Cities and helicopters will represent vertices in this graph and
there will be an edge between city and helicopter if there is a path between and the city that
helicopter lands on.
Firstly, lets find the maximum number of people that can be rescued without regard for the time needed.
This subproblem can be easily solved using the well-known max flow algorithm. We can see that costs of
edges and times of helicopter landing dont play any role here, so we can forget about them. Lets create
two new vertices:
and
, with
being connected to each city through an edge with
capacity equal to the number of people in city and
being connected to every helicopter through
an edge with capacity equal to the capacity of helicopter . We will set the capacity of edges between cities
and helicopters to infinity. Now its easy to see that the flow between
and
will be the
maximum number of people that can be rescued.
Now, if not all people can be rescued, we should just output this number. Otherwise we need to find the
minimal time needed to rescue all the people. In order to do that, we will make a use of the previous idea.
Lets try to answer the question whether we can save all the people within time D. If we remove all the
helicopters that land after time D, and if we remove all the edges
between the city and the
helicopter where there is no path of a distance no more than D, then the flow between
and
will tell us maximum number of people that can be rescued within time D.
Finally, lets note that if we can save all the people within time D, then we can save all the people within
time D+1, D+2, as well. Because of this we can do a binary search over time D, and find the minimal time
85
Qualifications
needed to save all the people.
Time complexity of this algorithm is:
where
is the maximal number of people that can be saved (up to 200), and
is the
maximal time needed to reach a helicopter from a city (no more than 1000). The
factor is there
because we have to find the minimal distance between each two cities, and it can be done using the FloydWarshall algorithm.
Solution by:
Name: Boris Grubi
School: Gimnazija Jovan Jovanovic Zmaj
E-mail: borisgrubic@gmail.com
86
Qualifications
output
99
60
-1
-1
-1
-1
-1
-1
-1
-1
10
10
10
10
-1
10
10
-3
66
Solution:
As it turned out, this was the hardest problem in the BubbleCup qualification rounds. Here we are asked to
put four rectangles on a given rectangular field without overlapping such that the sum of values inside
those four rectangles is maximized.
This problem can be solved using dynamic programming. Its easy to see that a state can be easily
represented by 5 numbers
where
represents upper left and
bottom right
corner of a rectangle in a given rectangular field where we are trying to put
number of rectangles such
that we maximize the sum of numbers inside those rectangles. Lets represent these values by a matrix
.
For
we can see that however we set two rectangles, there will always exists such a vertical or
horizontal line that doesnt pass through any rectangle (see figure 1). The same holds for
, as
87
Qualifications
shown in figure 2. For
there exist only 2 cases where this is not possible and those two cases are
shown in figure 3. Lets first solve the problem not considering those 2 cases.
Figure 1
To solve this we will make a use of this property we have just noted. So, since every case can be
separated by a vertical or horizontal line, we can just simply try every possible way. So, we can derive the
following recurrent equations (for
:
for
and
Figure 2
Figure 3
For
, we can note that we will either take the whole observed rectangle, or we will remove the first
or the last column or the first or the last row. So if we represent the sum of cells in rectangle
88
Qualifications
by a function
we have:
Please note that in the given equations we should take care of special cases where
or
the former case we should set
and
and in the latter
and
.
. In
Now lets deal with this sum function. This is well known and used really often. Lets represent by
the sum of cells in the rectangle
. How to calculate it? Well its easy to see that the following
holds:
, for
for
, for
, for
where
represents the value of the cell in row column in the given rectangular field.
So, how can we make a use of this matrix to calculate the sum in rectangle
? Well, we
can use the inclusion-exclusion principle and derive the following:
for
, for
, for
, for
Lets analyze the running time of this solution so far One thing to note is that starting from rectangle
, where and represent number of rows and number of columns of a given rectangular
field respectively, in one cut we can get to one of the following rectangles (see figure 4):
,
Note that here we have
states.
Figure 4
Following this, in two cuts we can get into following configurations (see figure 5):
,
89
Qualifications
Here weve got
different states.
Again in three cuts we can get into following configurations (see figure 6):
,
And finally here we have
different states.
Figure 5
Figure 6
, we should set
.
90
Qualifications
Now after weve got this solution, lets get back to erasing columns. After erasing first or last column
multiple times, we will end up with a rectangle of type
. Note that our rows are fixed. So,
the solution will be the sum of consecutive columns where rows are fixed. Lets say
now, which is
Now lets crack those two cases in picture 3. Here we will crack only the first case, because the second
one can be solved similarly. Here we will use more dynamic programming. Lets fix two columns and one
row, like in Figure 7. Now we would like to compute the best way to put the left and the bottom rectangle
such that the sum of cells inside them is maximal, the left rectangle is bounded by column
and the
bottom rectangle is bounded by row and column .
Figure 7
91
Qualifications
Of course, for
we set
Figure 8
We are almost there. Now again, fix two columns and a row for the top rectangle, as shown in Figure 8, and
make a use of previously calculated values to calculate best profit. In pseudocode:
res1 = -infinity
For c1 -> 2 to m 1:
For c2 -> c1 to m 1:
For r -> 1 to n 1:
A = dp[1][c1+1][r][m] + dp[r+1][c2+1][n][m]
B = f[c1][c2][r+1]
res1 = max(res, A + B)
One last thing to worry about in this problem is the memory limit. Memory complexity in this solution is
, which is too high. But note that we are using
memory only in
matrix, and we know that at
least one of the parameters of
of
has some nice value. Either
or
or
or
, so we can make a use of it, by representing all the states where
by
, all the states where
by
, all the states
where
by
and finally all the states where
by
. Note that in this way we decreased our memory complexity to
, which is
sufficient for this problem and completes the solution.
Solution by:
Name: Boris Grubi
School: Gimnazija Jovan Jovanovic Zmaj
E-mail: borisgrubic@gmail.com
92
Qualifications
93
Qualifications
Sample
input
output
3
0 291
0 292
0 300
0.333
1.000
0.000
0.579
2
0 300
291 300
2
0 291
291 300
7
0 292
0 88
0 14
0 300
292 88
88 300
14 300
0
Solution:
The problem seems to be quite difficult when you look at it for the first time. Nearly instantly, simulation
comes into mind. If we begin at one position of the graph and choose our way according to the probabilities
of the graph randomly the algorithm should work for a small graph. But there are some problems, since we
cannot be sure how often we have to run the algorithm to get good results, especially, because we do not
know very much about the structure of the graph.
So we have to look at the problem differently. Lets call the -th node and the probability that one arrives
at the hostel directly from the -th node
. If the node we look at is the hostel the probability is one and
if it is a tourist information it is zero. For the other nodes, we look at the neighbors. According to the
problem statement, each way has the same probability of being chosen. That is why we can use the
following simple formula:
For each node we get one linear equation. All in all we have equations with at most unknown values.
These equations are always solvable, since it is guaranteed that we can reach either a tourist information or
the hostel from our start position. If we have solved all the equations we know the probability of our start
position.
Figure 1 shows a small example. The graph is taken from the last test case in the problem statement. We
have the following equations which we need to solve.
(
94
Qualifications
If we solve these equations, we get the required result. The time complexity of the solution is
use the standard Gauss algorithm, which one learns at school.
if we
292
88
14
300
Solution by:
Name: Patrick Klitzke
School: Saarland University
E-mail: philologos14@googlemail.com
95
Qualifications
output
2
2
3
2
96
Qualifications
Solution:
Here we are presented with a rather interesting problem which is clearly geometric in nature. It doesn't
seem easy at first glance, however its solution is relatively simple to obtain (although formally proving the
mathematics behind it might be tough). Like most geometry-related problems, CIRCLES can be solved in a
number of ways; the approach we will explain here seems intuitively the easiest to comprehend.
Let's first analyze what the problem gives us, and what we must calculate. We are required to support
three kinds of operations: adding/removing a circle from the visible set, and answer queries asking for
the maximal amount of currently visible circles which can be intersected by an arbitrarily drawn straight
line.
Before going any further with the analysis, let's prove a theorem which will be the basis of our solution.
Theorem: For all possible placements of circles (with respect to the task's constraints), at least one of the
lines which intersects the maximal amount of them is infinitesimally close to one of the common
tangents for one of the pairs of circles.
Proof: Let
and let
97
Qualifications
( is a unit vector)
(radius at point of tangency is parallel to )
(same as prev.)
(orthogonality)
We have obtained a linear equation where the unknown is the vector . Once we obtain it is easy to
obtain the desired points of tangency:
When we have the points of tangency for each of the four possible tangents, it's easy to reformulate each
tangent in the form
, which we can use to handle the lines more easily later on.
A new question arises now: how can we correctly check whether a line intersects a circle? There are many
ways in which this can be done; here we will present a trigonometric approach. What we do essentially is
calculate the distance between the center and the line, and compare it to the radius. If it is lesser, then the
line intersects the circle. To calculate the distance we will construct a right triangle using the distance we
are looking for as one of the catheti, and the vertical distance (following the Y axis) between the center and
the line as the hypotenuse.
The vertical distance can be calculated easily; if we were to draw a line parallel to the given one which
intersects the center, this distance is the change in the y-intercept parameter (since the slope doesn't
change):
(definition of slope)
To avoid precision errors with the square root and possible sign issues, it is wise to calculate the square of
this distance instead, and compare it with the square of the radius. When we get the final amount of
98
Qualifications
intersections, we should return the result plus 2, because as described in the theorem, we can
infinitesimally shift or rotate the tangent to include the two circles it is common to, without excluding any
other circle.
Now the only remaining issue is how to store the circles efficiently. A good structure for this in C++ is
a map, since we can use it to easily assign IDs to circles with insertion and removal times of
. To
avoid calculating tangents each time, we can store their parameters ( and ) in a four-dimensional
array of size
, where
will store the fth (1st is , 2nd is ) parameter of
the zth tangent between circles with IDs and . This narrowly fits our memory limits, so it is a plausible
optimization.
Our algorithm is now easy to construct: when we receive an insertion command we insert a new circle in
the map and store common tangents between this circle and all other currently visible ones. When we
receive a deletion command we simply erase the given ID from the map, and when we are given a query we
calculate the amount of intersected circles for each common tangent of pairs of visible circles, and output
the maximum. An obvious optimization would simply output the previously calculated solution immediately
if we receive two query commands in a row.
The time complexity of extracting common tangents is
, and the time complexity of checking the
amount of intersections for a single line is
. This means that insertion commands are processed in
time, deletion commands in
time, and queries in
time. Hence, the overall asymptotic
time complexity of our algorithm is
, where
is the amount of queries. With the given
constraints, this solves the problem well ahead of the time limit. The memory complexity is
if we opt
to store all the previously calculated tangents, and
otherwise.
Solution by:
Name: Petar Velikovi, Teodor Von Burg
School: Matematika Gimnazija
E-mail: petrovy.velickovic@gmail.com, teodor.vonburg@gmail.com
99
Qualifications
Input
There is a single positive integer T on the first line of input. It stands for the number of test cases to follow.
Each test case is exactly five lines, containing description of the route between two cities A and B, located
on opposite sides of the rivers.
n
a0 a1 a2 ... an
h1 h2 ... hn
c
s0 s1 s2 ... sn
Here n is the number of the rivers which are parallel to each other, ai - the distances between rivers or
between rivers and cities, hi - the widths of the rivers, c - the distance between A and B along the axis
parallel to the river, si - the costs of the unit of the bridge through ith river and s0 - the cost of the unit of
the road. Example for n=2 you can see on the picture.
All integers in input are positive and less than 50, except c - it is less than 2000.
Output
For each test case your program should write a single number to the standard output, equal to the minimal
total cost of the route between A and B, accurate up to two digits after the decimal dot.
100
Qualifications
Sample
input
output
1
2
1 1 1
1 1
1
1 1 1
5.10
Solution:
Lets first denote things differently than in the problem statement in order to simplify the expressions
which come after. Let
stand for costs of building bridges or roads in tracks starting from the upper
one and let
be track widths. Imagine now we've built bridges and roads in each track. Let
denote their projections on horizontal axis. We can observe that
and that there will never
exist a 'zigzag' structure while building the roads (meaning we'll never drive back with respect to the
horizontal axis). It is obvious that
.
Now we can state the problem formally. We want to minimize cost function
as
has to hold.
101
into
Qualifications
Now we have a sum of monotonic functions which has to be equal to a constant c. We can simply binary
search and find when the equality holds. From this point on it is trivial to reconstruct the solution - when
we found just calculate all and then the total cost using the expressions given above.
References:
1. http://www.slimy.com/~steuard/teaching/tutorials/Lagrange.html
2. http://en.wikipedia.org/wiki/Lagrange_multiplier
Solution by:
Name: Filip Paveti
School: FER Zagreb
E-mail: fpavetic@gmail.com
102
Qualifications
there exists
= degree of polynomial
Input
The first line of input contain an integer T, T is number of test cases
of 2 lines:
integers
(0 d 18)
Output
For each test case, output the coefficient of polynomial h(x) separated by space. Each coefficient of
polynomial h(x) is guaranteed to be an integer.
Sample
input
5
0
13
1
-1 2
1
0 2
2
2 -5 9
3
23 9 21 104
output
13
0 1
1 1
1 2 3
31 41 59 26
Solution:
Since
is 0, so
.
103
is a polynomial,
. Since
Qualifications
, we get that :
((
(( )
( )
)
)
( )
(1)
ci = ad+1 (-1)d-i(
)+ ad (-1)d-i-1(
)++ ai+1 (
From the last formula we can easily see that if we know coefficients
calculate coefficient
(
) must be divisible by
we can easily
(
).
Complexity:
Given the total number of test cases
and
, binomial coefficients must be determined
before calculating the coefficients . Then the overall complexity is
.
Solution by:
Name: Predrag Miloevi
School: Gymnasium Svetozar Markovi, Ni
E-mail: predrag_93@live.com
104
Qualifications
output
2
1
7
3
10
Solution:
This problem turned out to be one of the easiest in special round. It is obvious that any iterative calculation
of factorial will time out. We can use Stirlings formula (approximation) to calculate the factorial faster.
Stirling's formula is in fact the first approximation to the following series:
( ) (
, so
is a
monotonically increasing function, so we can use binary search to speed up the solution. A properly
implemented solution should work in time, but there are still some possible mistakes. Pay attention to how
you are rounding. I prefer rounding up. And pay attention to the base case of the binary search. There can
be several numbers such that number of digits of their factorials is the same for those distinct numbers.
This can cause WA.
Solution by:
Name: Danilo Vunjak
School: Faculty of technical science
E-mail: kingarthurie@gmail.com
105
Qualifications
106
Qualifications
Sample
input
3
2
john judy 1
mary peter 1
3
john judy 7
john peter 2
judy peter 2
7
john judy 3
katie peter 4
john peter 2
judy mary 1
peter mary 2
john katie 1
katie mary 1
output
Case #1: INFINITE
Case #2: 4
Case #3: 3
Solution:
This problem is a very fine example of how a seemingly straightforward algorithm fails to perform in time
without some necessary optimization. It did prove to be one of the harder tasks of the round, even though
the ideas behind it are all relatively simple and easy to implement.
First of all let's analyze the problem and reformulate it. The introductory part is backstory and not relevant
to the solution. From the input explanation one can easily conclude that what we are given in the problem's
input is an undirected weighted graph, where each node corresponds to a person, each edge represents a
connection between two people, and its weight is the connection level between them. The output
explanation tells us what we are required to do. The task at hand is to find the lengths of the shortest
paths (smallest degree of separation) for each pair of people, and output the maximal length out of
those (or 'INFINITE' if there exists a disconnected pair).
Before getting to the main algorithm, let's first discuss the way we can easily (and effectively) transform the
input data into a graph. It is clearly inconvenient for the nodes to be stored as strings. So the first thing we
want to do is to transform each string into an integer; to do this we use hashing. The constraints on the
string lengths and the characters it can contain in this problem make hashing an ideal option, because we
can make a perfect hashing function (which is a one-to-one function two different strings can't map into
the same integer). There are at most 10 characters in each name, and they only consist of lowercase
characters of the English alphabet. By observing each character as a number from 1 26 (where 'a'
corresponds to 1, 'b' to 2, etc...) we can observe each string as an integer in base 27. Hence, the largest
mapped integer value we can get, knowing the constraints (if we were to map the string 'zzzzzzzzzz'), is
2710 1. This easily fits in a single 64-bit integer variable, so we have no need for any kind of modular
arithmetic here. It is obvious why the hashing function described here is perfect.
There are numerous ways in which we can use the obtained integers to assign an ID (ranging from 1 to N,
where N is the number of nodes) to each node in the graph. One of the ways is to store all the integers
obtained so far in a binary search tree, while storing the ID within each node of the tree as well as the
integer that represents it. For each new edge we are given, we take the mapped values for the names
involved in that edge and try to insert them in the tree; if they are already inserted then we know which ID
corresponds to them, and if not then they are assigned the first unused ID (for this we can use a variable
which starts off at 1 and increases every time a new leaf is added to the tree). This code can be typed very
quickly in C++ using the map structure, which is essentially a RB-Tree (balanced binary search tree) and
107
Qualifications
easily maps one value to another. The time complexity of the hashing is linear on the length of the string
(essentially constant with this task's constraints), and the time complexity of each insertion in the tree is
| | . This is done for each edge, so the overall complexity of the input processing is O(|E| log |V|),
where |E| is the amount of edges in the graph.
Now that we have a normalized graph, we can start discussing the solution to the problem. Let's first get
the case when the answer is 'INFINITE' out of the way; this is the answer iff the graph is not
connected. Connectivity can easily be checked in O(|V|) time complexity using a depth-first
search algorithm - a graph is connected iff a depth-first search visits all the nodes in a single
execution. Once we are sure that our graph is connected, we can carry on. There are two algorithms that
come to mind for solving this problem Floyd-Warshall algorithm and Dijkstra's algorithm with a binary
heap-implemented priority queue. Both of these algorithms, in their nave form, will likely fail to solve the
problem in time. Here we will mention a key optimization to Dijkstra's algorithm which makes it
successfully process the given test data a few seconds before the time limit.
Dijkstra's algorithm, unlike Floyd-Warshall, is a single-source shortest path algorithm, meaning that in one
execution it's going to find the shortest paths from one node to all others. It is clear that for this problem
we need to execute Dijkstra's algorithm N 1 times, to get all the possible shortest path lengths. However,
with each next execution we have more information than before, which we can use to lessen the amount
of operations the algorithm will do. When it is executed for the first time, Dijkstra's algorithm will initially
only put one node in the priority queue (the first source we picked), while setting the distances associated
with all others to infinity. When we execute Dijkstra's algorithm for the K-th time, we can use the shortest
path lengths from nodes {1, 2, , K-1} to node K as their initial distance (since the shortest path from node
A to node B in an undirected graph has the same length as the shortest path from B to A), and immediately
insert them in the priority queue and mark them as visited. This will avoid repeating any unnecessary
calculations we have done before while calculating the mentioned path lengths, and is sufficient to pass the
given time limit. It should be noted, however, that this is in no way the only (or the best, for that matter)
optimization which solves this task in time. It is simply one of the most obvious ones and it is very easy to
modify the already-made code for Dijkstra's algorithm to support it.
The asymptotic time complexity of a single execution of Dijkstra's algorithm is O((|E| + |V|) log |V|), and
we have to execute the algorithm once for each node in the graph, which gives the total complexity
of O(|V| (|E| + |V|) log |V|), which dominates the time required for processing the input and checking
for connectivity, so this is the overall asymptotic time complexity of the solution. The memory complexity
(for storing the previously calculated shortest path lengths) is O(|V|2).
Solution by:
Name: Petar Velikovi
School: Matematika Gimnazija
E-mail: petrovy.velickovic@gmail.com
108
Qualifications
output
10 3
-1 -1 1 1 1 1 3 10 10 10
2 3
1 10
5 10
0
1
4
3
Solution:
Its important to notice that the array is in order, so equal values are in a group. Assume we are given from
i to j query. Let
be the number of appearances of the most frequent number in the given interval. We
split the interval into two parts,
and
. Its easy to notice that:
If
If
then
appearances of
then
number of appearances of
in
in
+ number of
Answering the queries can be done using a data structure known as the segment tree. Every node of the
tree will contain the following:
109
)
)
Qualifications
Also, by
we denote
of the node in the segment tree which contains the interval
. The same goes for other values of nodes (
,
, ...)
Initialization of the tree: For every node which contains the interval
its clear that
,
. If we had initialized nodes which contain intervals
and
, we can initialize a node which contains the interval
. Its obvious that
and
. If
, its clear that all the values from to
are equal (since the array is in order), hence
. If not,
is equal to
. The same
holds for
. Finally, the number of appearances of the most frequent number:
If
(
do not contain the same numbers, hence
and
.
If not,
The only thing left now is answering the queries, which is easy once we have all the information from the
segment tree. All we have to do is to split the interval until we get intervals for which we have information
from the segment tree, and then we combine informations in the same way as we initialize the segment
tree.
Lets summarize:
Initialization of the segment tree takes
time. Answering the queries by going down the
tree and combining the data takes
time per query.
So the time complexity is
. Memory complexity is
Solution by:
Name: Marko Bakovi
School: First gymnasium in Kragujevac
E-mail: markobakovic95@gmail.com
110
111