Решение задачи К-периодичная гирлянда с Codeforces
С пояснением   Просмотров: 869
За один ход вы можете выбрать одну лампу и изменить ее состояние (то есть включить ее, если она выключена, и наоборот).
Гирлянда называется k-периодичной, если расстояние между каждой парой соседних включенных ламп равно в точности k. Рассмотрим случай k=3. Тогда гирлянды «00010010», «1001001», «00010» и «0» являются хорошими, а гирлянды «00101001», «1000001» и «01001100» не являются хорошими. Заметьте, что гирлянда не является цикличной, то есть первая включенная лампа не идет после последней включенной лампы и наоборот.
Ваша задача — найти минимальное количество ходов, необходимое для того, чтобы получить k-периодичную гирлянду из заданной.
Вам необходимо ответить на t независимых наборов тестовых данных.
Пояснение к задаче
Пусть t[i] равно строке, содержащей все символы s, имеющие индексы i,i+k,i+2k и так далее (то есть все такие позиции, которые имеют остаток i по модулю k). Допустим, мы выбрали, что все включенные лампы будут иметь остаток i по модулю k. Тогда нам необходимо удалить все единицы на позициях, которые не принадлежат этому остатку. Также, рассматривая строку ti, нам необходимо потратить минимальное количество ходов, чтобы сделать эту строку вида «последовательный блок из нулей, последовательный блок из единиц и еще подин последовательный блок из нулей», потому что рассмотрение символов по модулю k приведет нас именно к такому шаблону (заметьте, что некоторые блоки могут быть пустыми).
Как посчтиать ответ для строки ti за линейное время? Пусть dpi[p] равно количеству ходов, необходимому для того, чтобы исправить префикс ti до p-го символа таким образом, что p-й символ ti равен '1'. Пусть cnt(S,l,r) равно количеству единиц в S на отрезке [l;r]. Заметим, что мы можем посчитать все необходимые значения cnt за линейное время при помощи префиксных сумм. Тогда мы можем посчитать dpi[p] как min(cnt(ti,0,p−1)+[ti[p]≠ ′1′],dpi[p−1]+[ti[p]≠ ′1′]), где [x] равно значению булевого выражения x (1, если x является правдой и 0 в ином случае). Пусть len(s) равно длине s. Тогда настоящий ответ для строки t[i] может быть посчитан как ans[i]=min(cnt(t[i],0,len(t[i])−1),min[p]=0len(ti)−1(dpi[p]+cnt(t[i],p+1,len(t[i])−1))) (таким образом, мы рассмотрели случай, когда получившаяся строка не содержит единиц вообще, и рассмотрели каждую позицию как последнюю позицию какой-то единицы).
Таким образом, настоящий ответ может быть посчитан как mini=0k−1(ans[i]+cnt(s,0,len(s)−1)−cnt(t[i],0,len(t[i])−1)).
Асимптотика решения: O(n).
Автор: Администратор