Блог пользователя izban

Автор izban, 12 лет назад, По-русски

Обратите внимание на бонусы в некоторых задачах, и если вы умеете их решать, пожалуйста, напишите об этом в комментариях.

408A - Очередь на кассе

В задаче нужно было найти время ожидания для каждой очереди, просуммировав покупки по всем людям, и найти минимум.

408B - Гирлянда

В задаче нужно было найти максимально длинную гирлянду, которую можно составить из тех элементов, что у нас есть.
Во-первых, если какой-то цвет нужен, но его нет, то ответ — -1.
Иначе, ответ всегда существует, и является целым числом.
Просуммируем ответы по всем цветам по отдельности.
Пусть у нас есть a кусков бумаги некоторого цвета, а нужно — b. Тогда если a >  = b, то к ответу можно прибавить b — повесить b кусков по одному метру, а если a < b, то к ответу можно прибавить a, использовав все куски, что есть в наличии. Итого, каждый цвет дает к ответу min(a, b).

407A - Треугольник

В задаче требовалось расположить прямоугольный треугольник с катетами a, b на плоскости с вершинами в целых точках.
Если искомое расположение существует, то катет a всегда можно представить как вектор с целыми координатами A{x;y}, при чем a2 = x2 + y2. Переберем все возможные x (1 ≤ x ≤ a - 1), проверим, что y получается целым числом.
Вектор, перпендикулярный вектору {x;y}{ - y;x}. Возьмем вектор B{ - y / g;x / g}, где g = gcd(x, y). Треугольник можно уложить на плоскость лишь тогда, когда b делится нацело на |B|, где |B| — длина вектора B. Кандидат на ответ — треугольник (0;0)(x;y)( - y / g * b / |B|;x / g * b / |B|), нужно лишь не забыть проверку на то, что гипотенуза не параллельна осям координат.
Сложность решения — O(n).

407B - Длинный путь

В задаче требовалось промоделировать путь персонажа по графу.
Заметим, что если мы пришли в вершину i, то ребра во всех вершинах с номерами меньшими, чем i, повернуты в pi. Это дает нам возможность заметить рекуррентную формулу: пусть dpi — число шагов, необходимое, чтобы добраться из вершины 1 в вершину i, если все ребра изначально повернуты назад, в pi. тогда dpi + 1 = 2dpi + 2 - dppi. Ответом будет dpn + 1.
Сложность решения — O(n).

BONUS: Умеете ли вы решать задачу, если нет ограничения, что pi ≤ i? В такой формулировке задача становится более интересной, но я пока не знаю решения.

407C - Занимательный массив

В задаче требовалось научиться прибавлять в оффлайне на отрезке числа сочетаний.
Будем смотреть, как изменяется задача при увеличении k от малых чисел к большим.

1) Все запросы имеют K = 0
Прибавляется каждый раз единица на отрезке.
Для решения задачи нужно прибавить на некотором массиве b[] в ячейку b[L] единицу, вычесть из b[R + 1] единицу, а после выполнения всех операций построить массив a как массив сумм на префиксах массива b.

2) Все запросы имеют K = 1
Прибавляется арифметическая прогрессия 1 2 3 4 ...
Для решения задачи нужно прибавить на некотором массиве c[] в ячейку c[L] единицу, вычесть из с[R + 1] единицу. После выполнения всех операций можно построить массив b как массив сумм на префиксах массива c. В таком массиве мы на каждом отрезке прибавили единицу. Если после этого для каждого запроса вычесть из b[R + 1] число C(R — L + 1, 1) = (R — L + 1), и построить массив а как массив префиксных сумм над массивом b, несложно увидеть, что массив а будет ответом.

3) Все запросы имеют произвольное k
Пускай у нас есть массив a[N][K].
обобщая предыдущие случаи, можно понять, что если поступает запрос L, R, K, нужно сделать операции

a[L][K + 1] += 1
a[R + 1][j] -= C(k + 1 — j + r — l, k + 1 — j) для всех 1 <= j <= K + 1

после чего построить необходимые суммы на префиксах для всех значений K спускаясь от больших K к меньшим.
Доказать, что нужно отнимать именно такое число сочетаний, проще всего, если посмотреть, как расположены эти числа в треугольнике Паскаля — легко увидеть, что это число является суммой всего ряда чисел перед ним.
Сложность решения — O((n + m)k).

407D - Наибольшая подматрица 3

В задаче требовалось найти наибольшую по площади подматрицу, состоящую из различных чисел.
Будем идти от медленных решений к более быстрым.

1) Решение за O(n6): Перебираем две противоположные вершины прямоугольника-ответа и проверяем, что все числа внутри различны.

2) Решение за O(n4): Фиксируем верхнюю и нижнюю границы прямоугольника-ответа (O(n2)).
Используем метод двух указателей при переборе левой и правой границы: пока в прямоугольнике нет одинаковых чисел, двигаем правую границу, пока есть — двигаем левую границу. Проверка при сдвиге границы — O(n), сдвигов — O(n).

3) Решение за O(n3logn): Введем функцию maxR(Left): наибольшее значение Right, такое, что при фиксированных Up и Down в прямоугольнике (Up, Down, Left, Right) нет одинаковых чисел. Заметим, что для всех i выполняется maxR(i) <= maxR(i + 1).
Как изменяются значения этой функции при сдвиге Down вниз? Каждое значение maxR(Left) может либо остаться таким же (если отрезок(Down, Down, Left, maxR(Left)) добавил лишь новые числа), либо уменьшиться.
Когда maxR(Left) уменьшается? Лишь тогда, когда одно из чисел с только что добавленного отрезка уже было в прямоугольнике.
Сдвигая Down вниз рассмотрим все числа в ряду Down. Для каждого числа в столбце j найдем индексы i и k такие, что i <= j, в столбце j есть вхождение числа a[Down][j] между строками Up и Down-1, i — максимально; k >= j, в столбце k есть вхождение числа a[Down][j] между строками Up и Down-1, k — минимально. Найдя такие индексы i и k (для этого удобно использовать set, для каждого цвета храня столбцы, где он встречался на данный момент между строками Up и Down), можно обновить maxR[i] = j — 1, maxR[j] = k — 1. Этого будет достаточно. Несложно заметить, что после описанных действий, если мы прокинем по всем i = m..1 maxR[i] = min(maxR[i], maxR[i + 1]), то мы вновь будем иметь корректные значения функции maxR(Left), и можно пересчитать ответ для данных Up и Down за O(n).

4) Решение за O(n3):
Предыдущее решение, несмотря на хорошую асимптотику, требует хранения большого количества set'ов. Это работает очень медленно даже на небольших тестах.
Избавимся от логарифма. Set используется лишь при поиске ближайших слева и справа чисел, равных данному, лежащих в строках с номерами от Up до Down. Заметим, что при сдвиге границы Up ближайший сверху элемент для данного a[i][j] отдаляется. Это наводит на мысль, что, двигая Up снизу вверх, можно заставить ближайший к a[i][j] элемент приближаться к столбцу j, и теперь, сдвигая Up вверх, мы можем, взяв число с верхнего ряда, быстро (за O(n)) определить все числа такие, что он будет для них ближайшим, и обновить для них ближайшее число.
Такое решение использует O(n2) памяти и O(n3) времени.

BONUS: Умеете ли вы решать эту задачу быстрее, чем за O(n3)? У меня не получилось, но никаких предпосылок того, что решения нет, я не нашел.

407E - k-d-последовательность

На контесте задачу, к сожалению, никто не решил, но в дорешивании первым оказался hza, с чем мы его и поздравляем.
В задаче требовалось найти наидлиннейший подотрезок, удовлетворяющий условию.

Сведем задачу к d = 1.
Если d = 0, то ответ — наидлиннейший подотрезок из равных чисел, этот случай обрабатываем отдельно.
Если d ≠ 0, то заметим, что если на некотором отрезке есть два числа ai, aj таких, что ai % d ≠ aj % d, то этот отрезок не может быть хорошим.

Разобьем исходную подпоследовательность на отрезки подряд идущих чисел, дающих равные остатки от деления на d, поделим каждое число на d, будем решать для каждого отрезка задачу отдельно, сказав, что d = 1.

Заметим, что отрезок [L, R] является хорошим тогда и только тогда, когда max(L, R) — min(L, R) — (R — L) <= k, и на отрезке с L по R нет одинаковых чисел. Объясняется это просто — если на отрезке нет повторяющихся чисел, то max(L, R) — min(L, R) — (R — L) — именно количество чисел, которые необходимо добавить, чтобы отрезок состоял из всех чисел с min(L, R) по max(L, R).

Для каждого L найдем такое maxR[L], что на отрезке с L по maxR[L] нет повторяющихся чисел, а maxR[L] — максимально. Это делается за O(nlogn) любым способом, например, проходом с map'ом.

Научимся для каждого фиксированного L поддерживать массив a[R] = max(L, R) — min(L, R) — (R — L). Если у нас есть такой массив, то для того, чтбы найти ответ, необходимо быстро найти такое наибольшее R, что a[R] <= k.

Нам потребуются два стека и дерево отрезков с операциями "Прибавить число на отрезке", "Найти минимальный элемент на отрезке" и "Найти самое правое число, такое, что оно не превышает k". Будем перебирать L справа налево (от n до 1). Как выглядит функция max(L, R) при фиксированном L? Ее значения представляют собой набор отрезков, на которых максимумом является первый элемент отрезка. (пример: для массива 6 4 8 0 7 9 функция max(1, R) будет иметь вид 6 6 8 8 8 9) Как изменяется функция при сдвиге L влево? Некоторые отрезки поглощаются новым элементом, если новый элемент больше значения на отрезке. Заметив, что все значения массива не убывают, будем хранить все такие отрезки в стеке, а при добавлении нового элемента a[L] вытаскивать отрезки из стека, пока значение на вершине меньше нового, и добавим на стек новый отрезок, который покроет L и все, что мы вытащили. Если каждую операцию со стеком сопровождать запросом "Прибавить число на отрезке", то мы уже можем получить массив a[R] = max(L, R).
Функция min(L, R) ведет себя абсолютно аналогично, и используя второй стек мы получаем a[R] = max(L, R) — min(L, R). Для того, чтобы получить член (R — L) достаточно просто каждый раз при сдвиге L влево отнимать единицу на отрезке [L, n].

Теперь запрос "Найти самое правое число, такое, что оно не превышает k". Сначала дерево отрезков разбивает отрезок запроса L..R на log(n) отрезков длиной степени двойки. Разобьем запрос на такие отрезки и выберем самый правый отрезок, минимум на котором <= k. Теперь будем спускаться по этому отрезку вниз в дереве отрезков — если в правом сыне min <= k, то в правого, иначе в левого. Так мы найдем искомый элемент.

Итак, для каждого фиксированного L делаем запрос на отрезке L..maxR(L) о самом правом числе, не превышающем k. Это один из кандидатов на ответ. Все. Раз мы делаем запрос на отрезке, на котором нет различных чисел, то любое число на этом отрезке неотрицательно, и min работает корректно.

Суммарное время работы — O(nlogn).

BONUS: Задача и сама по себе не из простых, но умеет ли кто-нибудь решать ее по методу "навороти побольше"? Интересно, как решать хотя бы на дереве.

BONUS2: Есть очень быстрое решение за O(n2). Давайте для отрезка [L; R] так же посмотрим на значение f(L, R) = max(L..R) — min(L..R) — (R — L) — K. f(L, R) можно считать для отрезка за O(1). Если f(L, R) <= 0, то отрезок — кандидат на ответ. Если f(L, R) > 0, то следующий отрезок, который стоит рассмотреть — [L; R + f(L, R)], потому что для всех r: R < r < R + f(L, R) отрезок [L; r] не будет k-d последовательностью, поскольку при добавлении одного числа в отрезок f(L, R) может либо возрасти на произвольное число, либо уменьшиться на единицу. Если так написать решение за квадрат, используя для начального R при фиксированном L значение L + curAns, то решение в среднем работает очень быстро, и получает ТЛ лишь на специальных тестов. Вполне возможно, что это решение можно оптимизациями довести до такого, что оно пройдет все тесты.

Разбор задач Codeforces Round 239 (Div. 1)
Разбор задач Codeforces Round 239 (Div. 2)
  • Проголосовать: нравится
  • +56
  • Проголосовать: не нравится

»
12 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

А можно добавить авторские решения?

»
12 лет назад, скрыть # |
 
Проголосовать: нравится +3 Проголосовать: не нравится

Умеете ли вы решать задачу, если нет ограничения, что pi ≤ i? В такой формулировке задача становится более интересной.

Получается циклическая реккуррентная система. Как такое решать?

»
12 лет назад, скрыть # |
 
Проголосовать: нравится +2 Проголосовать: не нравится

Unable to understand 407A — Triangle.

Proof for this???

»
12 лет назад, скрыть # |
 
Проголосовать: нравится +31 Проголосовать: не нравится

BONUS: Умеете ли вы решать задачу, если нет ограничения, что pi ≤ i? В такой формулировке задача становится более интересной.

Весь контест думал над тем, умею ли я такое решать :( А ты умеешь?

P. S. Задачи очень клевые!

»
12 лет назад, скрыть # |
 
Проголосовать: нравится +7 Проголосовать: не нравится

I think many people are waiting for the Tutorial of other problems!!!please!!!!!

  • »
    »
    12 лет назад, скрыть # ^ |
     
    Проголосовать: нравится +4 Проголосовать: не нравится

    Sorry, I am running out of time, I'll translate that part of editorial as soon as I can. If you want to see editorial right now, you can try view russian version with Google Translate.

»
12 лет назад, скрыть # |
Rev. 2  
Проголосовать: нравится +4 Проголосовать: не нравится

what kind of black magic is this?!!

  • for Div-1 B, i submitted solution 6181964 in contest, and it gave AC in runtime 15ms.
  • just now, i submitted solution 6193342 in practice, and it gave AC in runtime 31ms.
»
12 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

http://mirror.codeforces.com/contest/408/problem/C http://mirror.codeforces.com/contest/408/problem/C

why does it is showing wrong answer for input : 15 20 my output: YES 0 0 9 12 -12 16

»
12 лет назад, скрыть # |
Rev. 3  
Проголосовать: нравится 0 Проголосовать: не нравится

I think there's a problem with this test-problem B.garland-DIV2: input : (yqfqfp/ tttwtqq) Answer is 2,right? but Checker log says: -1. Can anybody expain why?

»
12 лет назад, скрыть # |
 
Проголосовать: нравится +1 Проголосовать: не нравится

Can someone explain the solution to problem 407C please?

»
12 лет назад, скрыть # |
 
Проголосовать: нравится -8 Проголосовать: не нравится

How to solve the problem 407C — Curious Array. I think it is so difficult.

»
12 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

Someone that explains 407B better)?:)

  • »
    »
    12 лет назад, скрыть # ^ |
    Rev. 4  
    Проголосовать: нравится +1 Проголосовать: не нравится

    let us assume that dp[i] be the number of moves required to start at room i and come back to i.

    now when we move from room i to p[i], we would have odd number of crosses on room p[i], therefore we would need dp[p[i]] more moves to come back to p[i] and make it have even number of crosses. so after dp[p[i]]+1 moves, we would be at position p[i] + 1.
    solving similarly for other rooms, we can get dp[i] = 1 + (dp[p[i]]+1) + (dp[p[i]+1]+1) + ... + (dp[i-1]+1) (the first 1 is the initial move from i to p[i]).

    now u should be able to see that the final answer would be (dp[1]+1) + (dp[2]+1) + (dp[3]+1) + ... + (dp[n]+1).

    the above solution works in . it can be reduced to by using prefix sums.

  • »
    »
    12 лет назад, скрыть # ^ |
     
    Проголосовать: нравится +3 Проголосовать: не нравится

    suppose that you are in room k the 1st time (aka the number of crosses is odd), and the number in room k is p[k].

    let s[k] the steps you need to go from room k to room k+1.

    in order to do that:

    • you need 1 step to go from room k to room p;

    • you need s[p[k]]+s[p[k]+1]+s[p[k]+2]+...+s[k-1] steps to go from room p to room k. now the number of crosses is even;

    • you need 1 step to go from room k to room k+1.

    so

    s[k]=2+s[p[k]]+s[p[k]+1]+s[p[k]+2]+..+s[k-1]

    and of course

    answer=s[1]+s[2]+..+s[n]

    with n=1000 solving time is 30ms :)

    • »
      »
      »
      12 лет назад, скрыть # ^ |
       
      Проголосовать: нравится 0 Проголосовать: не нравится

      Can you explain the really short solution?

      "In this problem you had to simulate route of character in graph. Note that if you are in vertice i, then edges in all vertices with numbers less than i are turned to pi. It gives us opportunity to see a recurrence formula: let dpi be number of steps, needed to get from vertice 1 to vertice i, if all edges are rotated back, into pi. Then dpi + 1 = 2dpi + 2 - dppi. Answer will be dpn + 1."

      I don't really understand; what is a "rotated back" edge? What does it mean "numbers less than i are turned to pi"

      • »
        »
        »
        »
        10 лет назад, скрыть # ^ |
         
        Проголосовать: нравится 0 Проголосовать: не нравится

        Hello AkshajK, think of it this way.

        dp[i+1] is composed of three sums.

        dp[i+1] = S1 + S2 + S3

        S1 := dp[i], since we need to get to point i first.

        S2 := 2, one for the move back to p[i] and one for the jump from i to i+1

        S3 is more interesting. Once, we've jumped back to p[i], how many jumps does it take to get back to i?

        Jumps to reach (p[i]+1) := dp[p[i] + 1] — dp[ p[i] ] . Why? Because it's just the total number of moves to reach p[i] + 1 minus the number of jumps we needed originally to get to p[i] i.e dp[p[i]].

        Thus S3 := (dp[p[i] +1] — dp[p[i]]) + (dp[p[i] +2] — dp[p[i]+1]) + ... (dp[i] — dp[i-1])

        This reduces to, S3 := dp[i] — dp[p[i]]

        Adding the three sums should give you the final answer.

      • »
        »
        »
        »
        6 лет назад, скрыть # ^ |
         
        Проголосовать: нравится 0 Проголосовать: не нравится

        I understood the solution. I had a simple doubt.

        Let's say the input is:

        2

        2 2

        In this case according to me, the answer should be 3 (1->2->2->3). He only used the portal three times, but according to the solution it'll give the answer as 4.

        Am I missing something? Or is there an explanation?

        Thanks!

»
12 лет назад, скрыть # |
 
Проголосовать: нравится +32 Проголосовать: не нравится

6 days have passed and there are still no solutions to C-E. I can hardly call it soon...

»
12 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

Для каждого числа в столбце j найдем индексы i и k такие, что i <= j, в столбце j есть вхождение числа a[Down][j] между строками Up и Down-1, i — максимально ? По моему тут ошибка.

»
12 лет назад, скрыть # |
 
Проголосовать: нравится +7 Проголосовать: не нравится

There are no solutions for the last 3 challenging challenges, please speedup, we are waiting for that.

»
12 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

Why aren't there any solutions for the last 3 problems? Do the authors forget this blog???

»
11 лет назад, скрыть # |
 
Проголосовать: нравится -16 Проголосовать: не нравится

so many statement mistakes in this tutorial!!

»
8 лет назад, скрыть # |
 
Проголосовать: нравится +18 Проголосовать: не нравится

Anyone solving the 'Bonus' Section of Div1 B — Long Path?

»
7 лет назад, скрыть # |
Rev. 2  
Проголосовать: нравится 0 Проголосовать: не нравится

I'm trying to solve 407A — Triangle, I'm not able to understand the tutorial above. Why GCD is used? Also, how did we end up taking those points?

Can someone tell me any prereq. reading that I need to do before I'll be able to understand the concepts mentioned in tutorial above?

Thanks!!

  • »
    »
    7 лет назад, скрыть # ^ |
    Rev. 2  
    Проголосовать: нравится +1 Проголосовать: не нравится

    Let point where base and perpendicular meet be {x,y}. Then we can write other two points in form of the angle which line connecting them with {x,y} make with x-axes and radial distance. Let these points be {x1,y1} and {x2,y2}. Then,

    x1 = x + a*cos(theta) ; y1 = y + a*sin(theta)

    x2 = x — b*sin(theta) ; y2 = y + b*cos(theta)

    where theta is angle between line connecting {x,y} and {x1,y1} and horizontal axes.

    Now since x, x1 are integers therefore a*cos(theta) should also be integer.

    Let cos(theta) = p/q. Then q should be multiple of both a and b. Smallest such q will be lcm(a,b). Now , a*cos(theta) = a*(p/lcm(a,b)) = (p/(b/g)) = (p*g)/b which can only be integer between [-a,a] since, -1 <= cos(theta) <= 1.

»
7 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

Other way to optimize D:

Instead of using set use bitset of size maxn initially filled with zeros. Anytime we insert value at point i just set ith bit to 1. To find next filled element we can just use _Find_next on bitset, sadly bitset has no _Find_prev, but we can use #define private public to bypass it and implement our own _Find_prev

Code: 55948192

»
18 месяцев назад, скрыть # |
Rev. 2  
Проголосовать: нравится 0 Проголосовать: не нравится

For those struggling in problem Div2D, here's an alternative DP formulation, which is more aligned to the definition given in the statement

Let dp[i] = the number of steps needed to move from room i to room (i + 1).

Base case: dp[0] = 0 (we start in room 1)

For room i (1 ≤ i ≤ n):

  • Vasya first moves to room p[i] (1 step)
  • From p[i], he needs dp[p[i]] steps to reach room (p[i] + 1)
  • From (p[i] + 1), he needs dp[p[i] + 1] steps to reach room (p[i] + 2)
  • This continues until he reaches room i again
  • Finally, he takes 1 more step to reach room (i + 1)

Therefore, the recurrence relation is: dp[i] = 2 + sum(dp[j]) for j in [p[i], i)

The final answer is the sum(dp[i]) for (1 ≤ i ≤ n).

Time Complexity: O(n^2)

Optimization: While not necessary for the given constraints, we can optimize this to O(n) time complexity using prefix sums. This is the idea behind the editorial solution.