205A - Маленький Слоник и Роздол
Это была самая простая задача из набора. Нужно просто отсортировать все расстояния (при этом поддерживая индексы) и, если первые два расстояния равны, вывести "Still Rozdil", иначе вывести индекс первого элемента.
Сложность решения O(NlogN).
205B - Маленький Слоник и сортировка
В этой задачи нужно заметить тот факт (который несложно доказать, но он понятен даже интуитивно), что, так как массив нужно сделать неубывающим, если делать какую-то операцию, то r (правая граница) должна быть равна n. Действительно, подняв правую часть массива мы точно не ухудшим результат. После этого нужно идти слева направо и жадно делать необходимое количество операций на каждом шагу.
Сложность решения O(N).
205C - Маленький Слоник и промежуток
Естественно, для того что-бы решить задачу нужно написать функцию F(x) которая будет решать задачу на промежутке 0..x, тогда ответом будет F(r) - F(l - 1).
Опишем реализацию функции F(x). Если x < 10, результатом будем сам x. Пусть len — длина числа x, а x' — число x без первой и последней цифр, а xi — i-я цифра числа x (от 0 слева направо). Переберем первую цифру d (она и будет последней) и длину того что внутри (пусть это будет i). Тогда если i < len - 2 или (i = len - 2 и d < x0), к ответу нужно добавить 10i. Иначе, если i = len - 2 и d = x0 то к ответу нужно добавить x', а если еще и i = len - 2, d = x0 и xlen - 1 ≥ d то нужно добавить еще 1 к ответу.
Также эту задачу можно было решить используя ДП.
205D - Маленький Слоник и карточки
Эту задачу можно удобно решить используя структуру map, но можно и обойтись без нее (используя сортировку и бинарный поиск). Давайте переберем цвет-кандидат который и приведет к веселости набора, для каждого цвета узнаем минимальное количество переворачиваний (если возможно вообще) и выберем минимум. Если никакой цвет не подходит, ответ "-1". Для того чтобы найти минимальное количество переворачиваний нам нужно узнать два числа — количество карточек которые изначально лежат текущим цветом вверх, а также количество карточек у которых сзади есть текущий цвет (при этом сверху какой-то другой). Пусть это числа a и b. соответственно. Пусть m = (n + 1) / 2 — минимальное количество одинаковых карточек необходимых для того, что-бы сделать набор веселым. Тогда текущий цвет может сделать набор веселым только если a + b ≥ m. Если a ≥ m, то ничего переворачивать не надо, то есть ответ 0, иначе ответ равен m - a.
205E - Маленький Слоник и Фурик и Рубик
Задача на математическое ожидание. Здесь важно учесть факт линейности математического ожидания, иными словами, ответ для какой-то пары строк это сумма количеств совпадений по каждому символам алфавита. Поэтому давайте для каждого символа первой строки найдем вероятность того, что он войдет в ответ. Тогда общим ответом будет сумма этих вероятностей.
Пусть у нас текущий символ в первой строки с номером i (всюду 1-нумерация). Сначала решим задачу за O(N2). Переберем все позиции j левее i (или равные i) такие что Bj = Ai. Тогда для какой-то позиции нужно найти количество возможных пар строк таких, что в них именно эти два символы Ai и Bj совпали. Это количество будет равно j(n - i + 1) (j возможных символов слева и (n - i + 1) справа, поэтому общее количество это их произведение). Это будет O(N2). Так как все это — сумма, то ответ будет равен Si(n - i + 1), где Si — сумма всех позиций j таких, что Bj = Ai. Массив S можно несложно посчитать за линейное время. Аналогичным образом нужно обработать все индексы что правее i.
После того как количество пар подстрок в которых i-й символ первой строки имеет совпадение найдено (пусть это count), к ответу нужно добавить count / total, где total — полное количество возможных исходов, его можно найти циклом или несложной формулой.
Сложность решения O(N).
204D - Маленький Слоник и ретро строки
Для начала нам нужно решить следующую подзадачу: для каждого префикса найти количество его заполнений таких, что он не содержит подстроки длиной k состоящую только из букв B. Пусть это будет F(x), где x это номер последнего символа префикса. Давайте присвоим F(x) = F(x - 1) * cnt, где cnt = 2, если Sx = 'X', 1 иначе. После такого присвоения в результат могли быть включены некоторые способы такие, что блок из k есть в конце префикса (они могли быть включены только если в подстроке Sx - k + 1..x нет букв W, а символ Sx - k не есть B), а это плохо. Поэтому (если такое могло произойти) нужно от F(x) отнять F(x - k - 1), это уберет все плохие варианты.
Аналогичное ДП нужно посчитать для для суффиксов (или, иначе говоря, для реверсовной строки S), только здесь нужно избегать блоков из W.
Теперь подумаем как организовать все что-бы не появилось повторов. Давайте переберем позицию, в которой будет заканчиваться первый слева блок из k подряд идущих букв B. При этом будем перебирать эту позицию справа налево. Используя ранее подсчитано ДП мы можем найти количество вариантов заполнить все буквы левее так, что-бы там не образовался блок. Если писать решение за O(N2), то мы можем перебрать позицию, в которой будет начинаться первый справа блок из k букв W, аналогичным образом найти количество способов заполнить все правее что-бы там не образовался блок, а символы между левым и правым блоками мы, очевидно, можем заполнять как-угодно. Но, так как мы идем справа налево, мы можем по ходу поддерживать сумму этих количеств. Это обеспечит нам линейность решения.
204E - Маленький Слоник и строки
Для решения данной задачи воспользуемся свойствами суффиксного массива. Болле подробно о суффиксном массиве можно почитать здесь:
http://e-maxx.ru/algo/suffix_array
Для начала нужно конкатенировать все строки в одну, при этом разделяя их какими-то символами которые не встречаются в строках. Например, три строки abc, a, ab можно склеить в одну следующего вида: abc#a@ab. Теперь нам нужно построить суффиксный массив по новой строке, это позволит нам отсортировать все циклические сдвиги строки. При этом первый символ каждого циклического сдвига это либо вспомогательный символ, либо символ какой-то входной строки.
Заметим теперь что для того что-бы найти результат нам нужно для каждого циклического сдвига, начало которого принадлежит какой-то входной строке, найти максимальную длину его префикса такую, что этот префикс является подстрокой как минимум k входных строк. Это число можно искать бинарным поиском, но для этого нужно какую-то функцию которая бы отвечала на вопрос: а сколько есть различных входных строк которые содержат префикс длины len циклического сдвига номер x (Пусть это функция F(x, len)).
Как же сделать функцию F(x, len)? Рассмотрим все циклические сдвиги, префикс длины len которых ровен префиксу длины len x-го сдвига. Заметим что, так как все сдвиги отсортированы лексикографически, набор таких сдвигов будет представлен каким-то промежутком [l;r] (1 ≤ l ≤ x ≤ r). Как же найти этот промежуток? Для каждой пары соседних сдвигов можно найти их наибольший общий префикс. Тогда l, например, можно найти используя RMQ — для этого нужно найти самую правую пару соседних сдвигов (левее x) таких, что их наибольший общий префикс меньше len. Аналогично можно найти r. После этого у нас есть промежуток [l;r] и нужно найти количество различных строк которые соответствуют этим сдвигам (иными словами, найти количество различных чисел в подмассиве). Но, заметим, что самое количество различных нас не интересует, а интересует только не меньше ли оно за k или нет. Тогда пусть L[i] равно максимальному j (j ≤ i) такому, что количество различных чисел в помассиве [j;i] ровно k. Тогда если L[r] ≥ l то, логично, что и в промежутке [l;r] также будет не меньше k различных чисел.
Осталось заполнить массив L. Это довольно просто сделать используя структуру set (можно также использовать RMQ). Будем идти слева направо и в сете поддерживать индексы самых правых k различных чисел. Тогда если поступает какое-то число, то (если оно встречалось раньше) его прежнее вхождение нужно удалить из сета (если оно еще осталось) и вставить текущее. При этом если размер сета превышает k нужно извлекать минимальный элемент. Тогда если в какой-то позиции i размер сета есть k (после описанных выше изменений), это означает, что L[i] ровно минимальному элементу сета.
Так как мы O(N) раз используем бинарный поиск, а функция F(x, len) работает за O(logN), финальная асимптотика решения равна O(Nlog2N).
Задача 205С. У тех, кто кодит на Си преимущество. У них 10^18 в long long влазит. А тем, кто кодит на Паскале или на Делфи приходиться писать длинную арифметику. Вывод : переходите на Си.
int64?
Извините, значит это у меня баги. Ладно. Пойду дебажить...
я просто оставлю это здесь 1883566
Qword?
За что минусы? парень правильно говорит ...
Наверное, потому что ответ, даже 2, уже были даны выше.
Может SuprunovVlad не знает таких типов, вот я ему и написал еще один..
в задаче А (Div. 2) сложность, все-таки, O(N). Накой там сортировка?
Чтобы написать за минуту, а не за полторы)
Это какую же сортировку писать быстрее, чем два прохода по массиву?
std::sort
PS: Зачем два прохода по массиву. если достаточно одного?:)
Он на паскале пишет, там встроенного сорта нету, нужно самому писать, ну либо копировать из папки в паскале...
Так точно, капитан.
Arrays.sort(array); ?
Не у всех есть возможность.
Вам запрещают пользоваться другими языками? :(
Нет, просто не все знают несколько языков..
Если говорить о возможности, то возможность есть у всех. А вот желания изучить уже может не хватать.
Даже если есть желание выучить, на родном языке писать все равно лучше чем на другом, ИМХО.
Я понимаю, как натуральный язык может быть родным, но как таким может быть язык программирования?!
чтобы в один прекрасный момент пасть жертвой антиквиксорт теста (: Хотя, можно написать собственную рандомизированную версию квиксорта, и всегда ее использовать. BTW, огромное спасибо за CHelper. Замечательный плагин
Collections.shuffle(Arrays.asList(array));
Или, чтобы не было многократного снижения производительности:
Начиналось, напомню, все с того, что не хотим писать проход по массиву
А зачем это писать? :) Можно юзать тот же самый CHelper, ну или просто в сжатом виде вбить в шаблон.
P.S. Я сам все-таки
пишуне пишу, т.к. давно не попадались задачи, где нужно тупо отсортировать массив скаляров.Заводите массив Integer'ов, они сортятся mergesort'ом
Я вот как коммент написал через секунду понял, что кто-нибудь обязательно это напишет :)
204E можно решать за O(n) — построим суффиксное дерево склеенной строки, посчитаем для каждой вершины в оффлайне количество различных разделителей, достижимых из нее, после этого ответ считается линейным проходом по дереву
Задача E(div 2). Если поделить count на 2, то получится количество одинаковых подстрок двух строк. Прав ли я?
Владислав писал про E(div1).
А так нет, не правы. count — это всего лишь суммарное количество совпадений символов по всем парам подстрок одинаковой длины.
In "250A Little Elephant and Rozdil", It's no need to sort the distance.Just find ont the min_element and then check if it is unique, and the complexity is O(N) After all, it's such an easy problem that it is very easy solve. The O(N lg N) algorithm will not waste too much time, too.
Yep, I agree. I did the O(N) solution but in retrospect the O(Nlog(N)) solution would have been much quicker to code. (Not that the O(N) solution took that long).
I am a beginner. Can anyone explain in a greater detail the problem "205C — Little Elephant and Interval".? While solving the problem during the contest, I worked it out that between 10^i and 10^(i+1), there are 9*10^(i+1-2) desired numbers. But, I could not translate it into solving it for any l<r. It would be a great help if you can explain both F(r)-F(l-1) and DP approach to solve this problem.
It's not easy to code but a little difficult to understand.And please be patient to my poor English, thanks.
As this issue said " F(x) which solves the problem for the interval 0..x" and the problem is how to cauculate F(x)
let x = k * x1 + x2, x1 = 10 ^ n, ~/A means any number 1...9
For example , x = 3534 and x1 = 1000 x2 = 534
A~A, AA, A are allowed(as you know) (t1)
and 1~~1, 2~~2 are allowed too (t2)
At last, to the most difficult part, 3003 ... 3533 are allowed so (3534 — 3003) / 10 + 1 is the answer of the last part( 00...53 ) (t3)
Sum (t1), (t2), (t3), and you will get the answer.
I think my method is the same to the author, but it seems that we're describing it in different ways.
Thanks for your patience to my English(I seemed to say it twice)
I understand your explanation before i grasp editorial =)) It helps me a lot
And I got it from your code. Thanks
Can you please explain the DP solution of 205C — Little Elephant and Interval
To answer F(x), in my DP the state is D[i][j][k], 0 <= i <= 9, 1 <= j <= digits of max number, 0 <= k <= 1, is the total amount of this numbers which I can build, remaining j digits to fill and with the first non-zero digit i. The variable k tells if the numbers I have chosen are the same in x, for example if x = 3553 and I have chosen 30-- then k = 0 and the third number can be [0,9] but if I have chosen 35-- then k = 1 and I can only choose [0,5]. Then F(x) = D[0][digits of x][1].
I couldn't understand properly..it would be very nice of you ...if you could elaborate a bit
The base cases are when j = 1, i.e i only have to fill one digit, in case i = 0 and k = 1 it means all the digits I have filled are 0 and I have to build a number with only a digit, in that case the answer is the last digit of x, there are to more base cases, when i != 0 and k is 0 or 1, in the first case D[i][1][0] = (i <= last digit of x), and the second D[i][1][1] = 1. The k = 0indicates that no matter what digit I choose now the number will be lower than x, and if k = 1 I can only use digits which are lower to the last digit of x.
In the recursive case, I have to iterate through all possible digits I can use, in case k = 0 I can use whichever and otherwise I cant.
Here is my code:
Basically 'k' is a restriction on the current digit right? if k = 0, then we can fill the current digit from 0 to 9 if k = 1, then we can fill the current digit from 0 to digit[digit.length() — j] where digit is an array containing the individual digits of "R"
On problem 204E — LE Strings.
I understand the procedure used to fill L. But since L depends on K, don't we need to calculate it each time? That would take O(total_size) time in each binary search. If you precompute it we must do it for each value of K up to max_length. Precomputation takes O(total_size*max_length) which is inefficient. Another idea might be thinking of L as a function and only filling L[r], but that would take O(total_size) as well.
Can someone explain the logic of probelm Little Elephant and Interval m not gettin it ??
My Dp solution for "C. Little Elephant and Interval" is similar to idea in this topic http://stackoverflow.com/questions/22394257/how-to-count-find-integers-between-large-a-and-b-with-a-certain-property
My code here : http://mirror.codeforces.com/contest/204/submission/6435651 But i get WA on Test 18, i test several times on my PC or some online IDE, the output should be 100000000000000008, but the judge output isn't it . Someone can help me determine the bug in my code ? Thanks in advance :).
P/s : I have found the bug, array dp must be dp[21][21][21] instead of dp[20][20][20] @@.
actually there is a O(NlogN) solution for 204E — Little Elephant and Strings.
If someone interested in DP solution for Div2 C, here it is: https://mirror.codeforces.com/contest/204/submission/86109648.
We need to calculate dp[len][first_dig][last_dig] — count of numbers length of len with first digit = first_dig, last digit = last_dig. After that we can calculate get(R) — cnt of numbers with first digit equal to last digit from 1..R. Be careful then num.size() == R.size()!
If anyone is interested in the maths / greedy approach for C. Here it is Submission.
I don't know why everyone is solving by dp when it can be solved with more ease.
Can anyone tell me why my approach isn't working for 129A? ~~~~~~~~ //this is code public static void main(String[] args) { try { FastReader in = new FastReader(); FastWriter out = new FastWriter();
~~~~~~