432A - Выбор команд
В этой задаче нужно было посчитать количество студентов, которые еще могут участвовать в ACM ICPC, поделить его на три и округлить вниз. Это можно сделать так:
int cnt = 0; for(int i = 0; i < n; i++) if (5 - a[i] >= k) cnt++; int ans = cnt / 3;
432B - Футбольная форма
Посчитаем для каждой команды количество матчей в домашней форме. Для команды i это количество равно сумме числа всех домашних n - 1 игр и гостевых игр с такими команды, у которых цвет домашней формы совпадает с цветом гостевой формы команды i. Чтобы посчитать количество таких гостевых игр, можно заранее предпосчитать количество команд с определенным цветом домашней формы. Итоговое решение будет выглядеть примерно так:
for(int i = 0; i < n; i++) cnt[ x[i] ]++; for(int i = 0; i < n; i++) { ans_home[i] = n - 1; ans_home[i] += cnt[ y[i] ]; ans_away[i] = 2 * (n - 1) - ans_home[i]; }
432C - Простые обмены
Решение этой задачи можно описать следующим псевдо-кодом:
Перебираем элементы перестановки от 1 до n
Пока текущий элемент i не находится на позиции i
Пусть текущая позиция элемента i равна pos
Найти наибольшее простое меньшее либо равное pos - i + 1, обозначим его p
Поменять местами элементы в позициях pos и pos - p + 1
Можно доказать, что данный алгоритм всегда будет совершать не более 4n обменов. Проще всего это сделать, если написать код, который находит максимальное количество итераций цикла <ПОКА> для всех возможных pos - i.
Кроме всего прочего данный алгоритм нужно было реализовать оптимально. А именно поддерживать позиции элементов перестановки. В авторском решении была следующая функция:
void doSwap(int i, int j){ int x = a[i], y = a[j]; a[j] = x, pos[x] = j; a[i] = y, pos[y] = i; result.push_back(make_pair(i, j)); }
432D - Префиксы и суффиксы
Существует много решений этой задачи. Мы опишем решение, которое использует префикс функцию. Построим префикс функцию p строки s. Далее построим дерево, вершины которого — числа от 0 до |s|, а ребра идут из p[i] в i для каждого i. Корень дерева — это вершина 0. Далее для каждого v посчитаем сколько значений p[i] = v, обозначим его за cnt[v]. А затем для каждого v посчитаем сумму sum[v] всех cnt[u], где вершина u находится в поддереве вершины v.
Ответ на задачу считается считается следующим образом:
Найдем все длины префиксов, которые совпадают с суффиксами — это значения |s|, p[|s|], p[p[|s|]], p[p[p[|s|]]]... Для каждой такой длины L количество вхождений соответствующего префикса в строку это sum[L] + 1.
432E - Замощение квадратами
Разбор по задаче Е будет чуть позже, а пока всем понравившийся тест номер 6 :)
13 5 AAAAA AAAAA AAAAA AAAAA AAAAA BBBBB BBBBB BBBBB BBBBB BBBBB AAACA AAABB AAABB
Будем решать задачу стандартным методом — то есть будем заполнять таблицу от более значащих клеток к менее значащим. В каждую клетку будем стараться ставить букву как можно меньше.
Рассмотрим самую первую строку, понятно, что оптимальная раскраска этой строки начинается с нескольких букв A. На самом деле букв A в начале этой строки должно быть min(n, m). Поставив нужные буквы A в эту строку, мы должны поставить буквы A и в другие строки, чтобы образовать квадрат. Следующая буква (после закраски первого квадрата из A) в первой строке может быть только B.
Попробуем построить более общий алгоритм решения задачи. Предположим, что мы уже рассмотрели несколько строк, и теперь рассматриваем строку i. Вполне вероятно, что в нашей таблице в строке i некоторые клетки уже закрашены. Будем итерироваться по незакрашенным клеткам в порядке слева направо. Для каждой клетки будет перебирать ее цвет от A до Z. Нужно рассмотреть два случая:
Поставить в текущую клетку наименьшую букву, такую, что в соседних клетках нет такой буквы.
Если предыдущая клетка в строке была свободна на момент начала покраски i-й строки, то мы ее уже покрасили в какой-то цвет. Нужно попробовать объединить текущую клетку с квадратом, в котором находится предыдущая клетка.
Из двух описанных вариантов нужно выбрать тот, в котором цвет клетки получается меньше. Чтобы лучше понять, как должен работать алгоритм разберите его работу на примере n = 13 m = 5
any proof for problem C ?? I think most of the users solve it without any proof !!
Are there solutions other than the one described in the editorial? Maybe use a shell sort with prime increments?
i tired shell sort,it was giving TLE
Почему у меня решение выдает WA на 3-ем тесте ведь при таком примере
Мой ответ
Чекер на это выдает
Хотя если проверить вручную то он отсортирован
1 3 2 4.
Это по-вашему отсортирован?
Извините тупая ошибка)
Задача E шикарна!
Пока не догадался до построчной жадности (6641897), столько разного кода перепробовал.. на 1.5К строк точно наберется.
looking forward to problem E editorial
Here is the greedy algorithm to deal with problem E.
step 1: Start with an uncolored table.
step 2: Set the pointer to the first cell.
step 3: If the pointed cell is uncolored, run the greedy subroutine described below.
step 4: If the pointer hasn't reach the last cell, set the pointer to the next cell(from left to right and from top to bottom as the problem mentioned), then go to step 3.
step 5: end the algorithm
The greedy subroutine:
step 1: Mark an 1*1 square whose upperleft corner is the pointed cell.
step 2: Determine the color of the pointed cell by choosing the smallest possible letter without breaking the rules. This color(chosen color) will be used to color all the cells in the square.
step 3: Enlarge the square from n*n to (n+1)*(n+1) (the upperleft corner of the square is still the pointed cell)
step 4: If atleast one of the conditions below is true, cancel the last enlarge step(change back the size from (n+1)*(n+1) to n*n) and go to step 5. Else, go to step 3.
(1) Any of the cells in the square is already colored.
(2) Square go out of bound.
(3) the cell in upperright corner of the square can be colored with a smaller letter than the chosen color without connecting its neighbors outside the square. (connecting means two cells using same color and share a side, same as the definition in the problem)
(4) If color all the cells in the square with the chosen color, any of the cells in the square(only need to check the border cells) is connecting to some cell outside the square.
step 5: Color all the cells in the square using the chosen color in step 2.
step 6: end the subroutine.
thank you
I can't get the idea of problem A?? I thought of a much more difficult solution Any help?
Ну почему RE?
a>=1111 поэтому и RE
for 492 C, why is backward swapping not optimal?
My code gets WA(23490486) when I consider the case when element at i'th position is <i.
The same code gets AC(23490566) when I ignore this case and let it get sorted out in the next pass through. Why?
someone please explain question D. I am not getting what is written in the editorial above.
you can check how many characters from position i matches with the prefix of the string with z-algo in O(N) and determine the suffixes that matches prefix.
After that construct a suffix array and compute lcp of all suffixes with the suffix of position 1(whole string). you can build suffix array in nLOGn^2 and get all LCP in nLOGn. It will work because you are literally comparing the prefix with all possible substring start points. Store the LCP values in a frequency array and do a cumulative sum in reverse order. It will give you frequency of each prefix substring. It will work because if you found a LCP of 5 between two string that means you can also get a common prefix of (1,2,3,4).
my submission
O(N*LOGN*LOGN) getting TLE in D :(
In problem D, I understand that we can use the prefix function to determine efficiently the prefixes which are also the suffixes for the whole string. But I don't understand how are we calculating the count of sub-strings present in the string for each of that. Can somebody help me understand this in easy way please ?
you can check how many characters from position i matches with the prefix of the string with z-algo in O(N) and determine the suffixes that matches prefix.
After that construct a suffix array and compute lcp of all suffixes with the suffix of position 1(whole string). you can build suffix array in nLOGn^2 and get all LCP in nLOGn. It will work because you are literally comparing the prefix with all possible substring start points. Store the LCP values in a frequency array and do a cumulative sum in reverse order. It will give you frequency of each prefix substring. It will work because if you found a LCP of 5 between two string that means you can also get a common prefix of (1,2,3,4).
my submission
In problem D, you can simply calculate Z function and get the answer. No need for calculating suffix array and LCP. for a given prefix of length l, check whether z[n-l+1]=l or not. if Yes, then simply count how many integers in Z are greater than l by lower bound.
Submission : https://mirror.codeforces.com/contest/432/submission/47315796
(In case you are stuck with this problem(D) and just saw this beautiful idea and want a C++ code for the same)
https://mirror.codeforces.com/contest/432/submission/51429362 (Thanks for this awesome idea)
Thanks
Thank you! Awesome solution. Got to learn Z function from it. Here is the submission (easier to understand, I think) if someone is interested.
wow it's a very short and nice idea thanks
The Z-function method is obviously simpler and more intuitive. here.
Now, let's understand how the prefix-function method works. here.
Checking which prefixes-suffixes match is pretty straightforward. $$$pi[N]$$$ stores the length of the longest proper prefix which is also a suffix. So, this is our first matching prefix-suffix. Now, $$$pi[pi[N]]$$$ stores the length of the longest matching prefix-suffix of length less than $$$pi[N]$$$. Similarly, $$$pi[pi[pi[N]]]$$$ stores the length of the longest matching prefix-suffix whose length is less than $$$pi[pi[N]]$$$, and so on, until finally the length of our prefix becomes $$$0$$$.
Now, how does the less intuitive tree method work, for counting the number of occurrences of each prefix. There are $$$N+1$$$ vertices from $$$0$$$ to $$$N$$$, each denoting a prefix of that length. There is at least once occurrence of each prefix. Also, $$$pi[v]$$$ denotes that there is an occurrence of the prefix of length $$$pi[v]$$$. Now, for each vertex $$$v$$$, we add an edge from vertex $$$pi[v]$$$ to $$$v$$$. Then, the number of occurrences of a vertex of length $$$v$$$ will be $$$1$$$ $$$+$$$ frequency of $$$v$$$ in the $$$pi$$$ array $$$+$$$ sum of all occurrences of its immediate children in the tree.
Why? $$$pi[v]$$$ signifies that the prefix of length $$$pi[v]$$$ is the immediate fallback for the prefix of length $$$v$$$, meaning: the prefix of length $$$pi[v]$$$ is the next longest prefix which will definitely be present in any string which contains the prefix of length $$$v$$$. So, a prefix of length $$$v$$$ will be contained in any prefix of length $$$u$$$, such that $$$pi[u]=v$$$. So, just adding the contributions of the immediate children in the tree gives us the contribution of all places where the prefix of length $$$v$$$ was inside another prefix of a longer length, and prevents over-counting.
432D can also be solving in O(nlogn) using hashing and binary search. Submission link
Although it is definitely not recommended as it is way more complicated than the LPS approach, and also is very easy to get wrong (too many modulo operations) or TLE (tight TL with nlogn complexity). But in any case, if someone else was also trying hashing and couldn't get it to work, this could help.
432D can also be solving in O(nlogn) using hashing and binary search. Submission link
Although it is definitely not recommended as it is way more complicated than the LPS approach, and also is very easy to get wrong (too many modulo operations) or TLE (tight TL with nlogn complexity). But in any case, if someone else was also trying hashing and couldn't get it to work, this could help.
It can also be solve by using suffix array, here's my shitty code(no one can understand) 86931883
It should've give TLE but it didn't, idk why.
D can be solved in O(n) simply using the z function. Steps
I. Using the z vector, construct vector<bool> good such that good[L] == true iff the prefix of length L is also a suffix.
II. Using the z vector, construct vector<int> cnt such that cnt[L] = number of appearances of the prefix of length L as a substring of s.
III. Using cnt and good, print the answer.
My submission: 82358099
I tried to solve Problem D using KMP but I am getting WA on test case 11. I am able to calculate L values but there is some problem while calculating sum. My code
Is there a way to solve this problem using KMP
[submission:217162339 Aug/05/2023] Problem D solution using prefix function
if any ques please ask!
Is there a simple way to solve problem D without prefix function, kmp or z function?
z functions and ordered set for count