Разбор задач Четвертой командной олимпиады
Difference between ru8 and ru9, changed 148 character(s)
**_Доброго времени суток!_**↵

Предлагаю обсудить задачи прошедшей олимпиады. По ходу буду добавлять разборы.↵

_**Разбор задач.**_↵

**Задача A.**↵

_Разбор от [user:Alex_2oo8,201
4-115-06-249]._↵

Всегда существует оптимальное решение следующего вида — разобьем всю последовательность на отрезочки и сначала заберем все числа из первого отрезочка (внутри отрезочка берем числа в обратном порядке), потом из второго отрезочка и так далее. К примеру, если мы разбили последовательность на отрезки вот так: <span class="tex-span">[<i>a</i><sub class="lower-index">1</sub>&thinsp;<i>a</i><sub class="lower-index">2</sub>&thinsp;<i>a</i><sub class="lower-index">3</sub>][<i>a</i><sub class="lower-index">4</sub>&thinsp;<i>a</i><sub class="lower-index">5</sub>][<i>a</i><sub class="lower-index">6</sub>&thinsp;<i>a</i><sub class="lower-index">7</sub>&thinsp;<i>a</i><sub class="lower-index">8</sub>&thinsp;<i>a</i><sub class="lower-index">9</sub>]</span>, то забирать числа будем в порядке <span class="tex-span"><i>a</i><sub class="lower-index">3</sub>,&thinsp;<i>a</i><sub class="lower-index">2</sub>,&thinsp;<i>a</i><sub class="lower-index">1</sub>,&thinsp;<i>a</i><sub class="lower-index">5</sub>,&thinsp;<i>a</i><sub class="lower-index">4</sub>,&thinsp;<i>a</i><sub class="lower-index">9</sub>,&thinsp;<i>a</i><sub class="lower-index">8</sub>,&thinsp;<i>a</i><sub class="lower-index">7</sub>,&thinsp;<i>a</i><sub class="lower-index">6</sub></span>. Доказывать это сейчас не буду.↵

Дальше получается довольно простое ДП: <span class="tex-span"><i>f</i>(<i>k</i>)&thinsp;-&thinsp;</span> -  максимальная сумма, которую можно получить убрав префикс длины <span class="tex-span"><i>k</i></span>. Переход будет такой:↵

- <span class="tex-span"><i>f</i>(<i>k</i>)&thinsp;=&thinsp;<i>f</i>(<i>k</i>&thinsp;-&thinsp;1)&thinsp;+&thinsp;<i>a</i><sub class="lower-index"><i>k</i>&thinsp;+&thinsp;1</sub></span>, если последний отрезочек будет длины <span class="tex-span">1</span>;↵
 ↵
- ![ ](http://espresso.codeforces.com/b8b8b32ebe1e2a72502b3ae775b17595c86c6254.png), если последний отрезочек — <span class="tex-span">[<i>j</i>,&thinsp;<i>k</i>]</span>.↵

- Замечаем, что второй переход можно записать вот так:↵

![ ](http://espresso.codeforces.com/061699eea5795887d4f8736741d14210e3450a22.png), где <span class="tex-span"><i>S</i></span> — префиксные суммы и получаем константный переход.↵

**Задача C.**↵

_Решение от [user:
Second_Hand,2014-11EXM_KG,2015-06-249]._↵

После долгих размышлений я увидел закономерность. Итог:↵

~~~~~↵
int s[][5] = {↵
    {1, 2, 3, 4, 5},↵
    {4, 5, 1, 2, 3},↵
    {2, 3, 4, 5, 1},↵
    {5, 1, 2, 3, 4},↵
    {3, 4, 5, 1, 2},↵
};↵
int main() {↵
    freopen(NAME".in", "r", stdin);↵
    freopen(NAME".out", "w", stdout);↵

    int n, i, j, m, a[111][111];↵

    scanf("%d%d", &n, &m);↵
    for(i = 0; i < n; i ++)↵
        for(j = 0; j < m; j ++)↵
            a[i][j] = s[i % 5][j % 5];↵

    for(i = 0; i < n; i ++){↵
        for(j = 0; j < m; j ++)↵
            printf("%d ", a[i][j]);↵
        printf("\n");↵
    }↵

    return 0;↵
}↵
~~~~~↵

**Задача D.**↵

_Разбор от [user:
king_of_hakers,2014-11heavenly_phoenix,2015-06-249]._↵

[Код](http://ideone.com/GaCAIx).↵

**Задача E.**↵

_Разбор от [user:SEFI,201
4-115-06-249]._↵

Простая динамика, не требует объяснения.↵


~~~~~↵
int main(){↵
    cnt [0] = 1;↵
    for (i =  1; n >= i ; i++){↵
        cnt[i] += cnt[i - 1];cnt[i]%=md;↵
        for (j =  i - 1; j>=1 ; j--){if(a[j] > a[j + 1])break;cnt[i] += cnt[j - 1];cnt[i]%=md;}↵
        for (j =  i - 1; j>=1 ; j--){if(a[j] < a[j + 1])break;cnt[i] += cnt[j - 1];cnt[i]%=md;}↵
        long long inter = 0;↵
        for (j =  i - 1; j>=1 ; j--){↵
            if(a[j] != a[j + 1])break;↵
            inter += cnt[j - 1];↵
        }↵
        cnt [i] -= inter;↵
        cnt [i] = (cnt[i] + md) % md;↵
    }↵
    cout << cnt[ n ] << endl;↵
 ↵
    return 0;↵
}↵
~~~~~↵

**Задача G.**↵

_Разбор от [user:
Second_Hand,2014-11EXM_KG,2015-06-249]._↵

Простой жадный алгоритм. На каждом этапе будем уравнивать предыдущий уровень с текущим пока это возможно. Если в конце остались лишние кубики (обозначим их как <span class="tex-span"><i>OST</i></span>), то ответом будет <span class="tex-span"><i>текущая высота стены + OST / N</i></span>.↵

Для лучшего понимания выкладываю [код](http://ideone.com/nq7WOm).↵

**Задача I.**↵

_Разбор от [user:
king_of_hakers,2014-11heavenly_phoenix,2015-06-249]._↵

[Код](http://ideone.com/9lsMJ5).↵

**Задача L.**↵

_Разбор от [user:pva701,201
4-115-06-249]._↵

- Первый факт — рассмотрим два возможных отрезка (произвольных длин), кандидатов на ответ, для которых выполнено условие, они либо не пересекаются, либо один вкладывается в другой, потому что если они как-то пересекаются, то у этих отрезков концевые элементы равны — поэтому можем просто взять один отрезок большей длины, таким образом увеличив длину.↵

- Т.е можем разбить весь массив на непересекающиеся подряд идущие отрезки. если запрос был просто на массиве — нам нужно было выбрать максимальный из этих отрезков.↵

- Посчитаем для каждого <span class="tex-span"><i>i</i></span>, такой максимальный индекс <span class="tex-span"><i>f[i] (f[i] >= i)</i></span>, что отрезок <span class="tex-span"><i>[i..f[i]]</i></span> удовлетворяет условию.↵

- Теперь, когда приходит запрос, начнем в <span class="tex-span"><i>l</i></span>, перейдем в <span class="tex-span"><i>f[l] + 1</i></span>, затем в <span class="tex-span"><i>f[f[l] + 1] + 1</i></span>, и т.д, т.е будем прыгать на элемент после правой границы отрезка <span class="tex-span"><i>[i..f[i]]</i></span>, сохраняя максимум среди длин всех отрезков, по которым прошли. рано или поздно наступит следующее: либо мы просто придем в <span class="tex-span"><i>r</i></span> (вернее, на следующий после <span class="tex-span"><i>r</i></span>) — тогда все, максимум найден, либо следующий прыжок из <span class="tex-span"><i>i</i></span> будет за правую границу, т.е <span class="tex-span"><i>f[i] > r</i></span>, отметим, что в этом случае <span class="tex-span"><i>a[i]</i></span> будет больше либо равен всех элементов на суффиксе <span class="tex-span"><i>[i..r]</i></span>. тогда начнем ту же самую процедуру с <span class="tex-span"><i>r</i></span> (мы так же заранее для всех <span class="tex-span"><i>j</i></span> посчитали массив <span class="tex-span"><i>g[j]</i></span> — минимальный индекс, такой что <span class="tex-span"><i>[g[j]..j]</i></span> удовлетворяет условию). рано или поздно, <span class="tex-span"><i>g[j]</i></span> станет меньше, чем <span class="tex-span"><i>l</i></span>. тогда <span class="tex-span"><i>a[j] = a[i]</i></span>, т.к. если бы они были неравны, то мы могли перейти из <span class="tex-span"><i>j</i></span> не за <span class="tex-span"><i>l</i></span> (<span class="tex-span"><i>g[j]</i></span> был бы больше <span class="tex-span"><i>l</i></span>), т.к. <span class="tex-span"><i>a[i]</i></span> был бы больше <span class="tex-span"><i>a[j]</i></span> (как мы ранее отметили). Т.е. остается один отрезок, который нельзя никак уже разбить <span class="tex-span"><i>[i..j]</i></span>, учитываем его в нашем ответе.↵

- Последний шаг — все вот эти переходы (<span class="tex-span"><i>f[i]</i></span>, <span class="tex-span"><i>g[j]</i></span>) предподсчитаем в массив двоичных подъемов, и будем делать наши прыжки за <span class="tex-span"><i>log N</i></span>.↵

Асимптотика &mdash; ![ ](http://espresso.codeforces.com/fbe14fd8eba5da6f86e2af98224ce4128b1b632a.png)↵

**Задача J.**↵

_Разбор от [user:netman,201
4-115-06-249]._↵

Сначала очень просто можно узнать, какое максимальное число вхождений у нас может быть.↵
Просто возьмем и посчитаем, какое максимальное кол-во вхождений какой-нибудь буквы мы имеем. Назовем это кол-во вхождений <span class="tex-span"><i>need</i></span>.↵

Давайте научимся проверять какую-нибудь длину <span class="tex-span"><i>len</i></span>. Проверять длину <span class="tex-span"><i>len</i></span> — значит узнать, есть ли у нас такая подстрока длины <span class="tex-span"><i>len</i></span>, что она имеет <span class="tex-span"><i>need</i></span> непересекающихся вхождений.↵

Это можно делать за используя полиноминальные хэши. Посчитаем хэш всех подстрок длины <span class="tex-span"><i>len</i></span>. Выпишем такие пары <span class="tex-span">(<i>hash</i>,&thinsp;<i>position</i>)</span> — хэш подстроки и позиция подстроки. Теперь давайте для каждого уникального <span class="tex-span"><i>hash</i></span> выпишем все его <span class="tex-span"><i>position</i></span> в возрастающем порядке. Теперь, зная все <span class="tex-span"><i>position</i></span> для фиксированного <span class="tex-span"><i>hash</i></span> не составляет труда посчитать максимальную подпоследовательность из этих позиций, что разница между соседними элементами подпоследовательности больше либо равна <span class="tex-span"><i>len</i></span> (это условие нужно, потому что мы ищем непересекающиеся вхождения). Это можно легко подсчитать используя ДП:↵

Пусть <span class="tex-span"><i>a</i></span> — это подпоследовательность, в которой нужно найти максимальную подпоследовательность, чтобы соседние элементы различались не меньше чем на <span class="tex-span"><i>len</i></span>. Напоминаю, что все числа в этой последовательности в возрастающем порядке.↵

Теперь можно просто считать следующее ДП:↵

<span class="tex-span"><i>f</i><sub class="lower-index"><i>i</i></sub></span> — максимальная длина подпоследовательности из префикса <span class="tex-span"><i>a</i></span> длины <span class="tex-span"><i>i</i></span>. Понятно, что <span class="tex-span"><i>f</i><sub class="lower-index">0</sub>&thinsp;=&thinsp;0</span>.↵

Подсчет данного ДП ведется так:↵

<span class="tex-span"><i>f</i><sub class="lower-index"><i>i</i></sub>&thinsp;=&thinsp;<i>max</i>(<i>f</i><sub class="lower-index"><i>j</i></sub>,&thinsp;<i>f</i><sub class="lower-index">0</sub>)&thinsp;+&thinsp;1</span>, где <span class="tex-span"><i>j</i></span> — такая максимальная позиция, что <span class="tex-span"><i>a</i><sub class="lower-index"><i>i</i></sub>&thinsp;-&thinsp;<i>a</i><sub class="lower-index"><i>j</i></sub>&thinsp;≥&thinsp;<i>len</i></span>. Если такой позиции нет, то <span class="tex-span"><i>j = 0</i></span>. Найти такое <span class="tex-span"><i>j</i></span> можно бинарным поиском.↵

Как говорилось выше: давайте для каждого уникального <span class="tex-span"><i>hash</i></span> выпишем все его позиции и запустим на них вышеописанное ДП. И возьмем максимум среди всех результатов запуска ДП. Это и будет максимальное кол-во непересекающихся вхождений строки, имеющей длину <span class="tex-span"><i>len</i></span>. Теперь легко проверить подходит длина <span class="tex-span"><i>len</i></span> или нет.↵

Также надо заметить, что если подходит длина <span class="tex-span"><i>len</i></span>, то и длина <span class="tex-span"><i>len &mdash; 1</i></span> тоже подходит, значит можно использовать бинарный поиск, чтобы найти максимальное <span class="tex-span"><i>len</i></span>, которое подходит.↵

Итоговая асимптотика решения: ![ ](http://espresso.codeforces.com/d49d4cd7c5453c28aaa5aef013382ea54a5f0fc9.png)↵

Для лучшего понимания выкладываю [код](http://pastie.org/private/94dad4cpjxcthwaulrqpg).↵

_Решение от [user:izban,201
4-115-06-249]._↵

Есть решение проще.↵

Сначала найдем <span class="tex-span"><i>need</i></span>. Теперь фиксируем первую букву ответа (26 вариантов), и перебираем длину ответа, добавляя новый символ — суммарно будет сделано не больше <span class="tex-span"><i>n</i></span> операций для каждой буквы. Итого, решение за <span class="tex-span"><i>26n</i></span>. [Код](http://pastebin.com/2QU1hgLa).↵

**P.S.** Осталось немного, отписывайтесь.

History

 
 
 
 
Revisions
 
 
  Rev. Lang. By When Δ Comment
ru9 Russian Azret 2015-06-29 19:52:45 148
ru8 Russian Azret 2014-11-26 19:18:44 -
ru7 Russian Azret 2014-11-24 18:52:21 -
ru6 Russian Azret 2014-11-24 13:25:11 -
ru5 Russian Azret 2014-11-24 13:19:41 -
ru4 Russian Azret 2014-11-24 13:03:43 -
ru3 Russian Azret 2014-11-24 11:49:52 -
ru2 Russian Azret 2014-11-24 11:47:32 -
ru1 Russian Azret 2014-11-24 11:32:08 -