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

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

Спасибо всем, кто написал раунд. Надеюсь, задачки вам понравились.

A — Фотографии Брейна

Нужно сделать ровно то, что написано в задачке: считать все символы, и, если есть хоть один из набора {C, M, Y} вывести "#Color" иначе — "#Black&White"

B — Пекарня

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

Таким образом, задача сводится к следующей: выбрать два соседних города так, чтобы в одном был склад, а в другом — нет. Для этого просто перебираем все города со складом, среди соседей каждого ищем город без склада и обновляем ответ. Если такой пары городов нет, выводим -1.

C — Пифагоровы тройки

Пожалуй, самая интересная задачка этого раунда.

Формализуем задачку:

Дано число a. Найти такие два числа b и c, чтобы выполнялось одно из следующих двух равенств:

a2 = b2 + c2 или a2 = abs(b2 - c2)

Давайте разберемся, когда ответ найти невозможно.

Если а = 1. Доказательство:

1 = b2 + c2 — невозможно

1 = abs(b2 - c2) — невозможно, т. к. не существует таких двух квадратов чисел, что разница между ними равна 1.

Если a = 2. Доказательство:

4 = b2 + c2 — невозможно.

4 = abs(b2 - c2) — невозможно, т. к. минимальная разность квадратов двух чисел, больших единицы равна 5.

Теперь решение для остальных чисел:

Если а — нечетное:

b = a2 / 2, c = a2 / 2 + 1, где " / " — целочисленное деление.

Тогда c2 - b2 = (c - b) * (c + b) = (1) * (a2) = a2.

Если a — четное:

Поделим а на 2. Тогда получится либо нечетное число, в таком случае, решаем задачку для (a / 2), а потом домножаем b и c на два:

b = (a2 / 4) * 2, c = (a2 / 4 + 1) * 2, где " / " — целочисленное деление.

Либо получится опять четное число. В этом случае исходное число а кратно четырем. И для решения используем известную Пифагорову тройку {3, 4, 5}:

b = 3 * (a / 4)

c = 5 * (a / 4)

D — Персистентный шкаф

Решение №1:

Заметим, что данные подаются все и сразу(offline). Тогда мы можем построить дерево версий, потом запустить DFS из корня и честно обрабатывать каждый запрос при переходе из вершины в вершину.

Решение №2:

Заметим, что Алина не использует операции, которые относятся к столбцам. Мы можем завести массив версий полок, а каждую версию шкафа представлять в виде массива индексов соответствующих полок и явно её хранить. Тогда при операции, как-то изменяющей шкаф, создается новая версия полки, которая была изменена, индекс этой версии записывается на позицию прежней полки. Этот подход избавляет решение от использование лишней памяти для хранения ненужной информации.

E — Гирлянды

Давайте обрабатывать каждый запрос следующим образом:

Пройдем по "рамке" запроса и запомним лампы гирлянд, которые лежит на границе. Тогда, чтобы для конкретной гирлянды найти, какая её часть лежит внутри запроса, просуммируем все её отрезки, концами которых являются лампы, лежащие на "рамке".

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

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

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

Кто может чуть более подробно разъяснить 2е решение задачи D. Как-то не понятно как должны изменяться со временем хранимые в памяти данные.

  • »
    »
    8 лет назад, # ^ |
    Rev. 5   Проголосовать: нравится 0 Проголосовать: не нравится

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

    По памяти в итоге 10^5 * 10^3 для полок и 10^5 * 10^3 * 4 для шкафов. Что-то около 490 мб должно выходить, кажется.

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

      Второе решение задачи D в итоге оффлайновое или онлайновое? Существует ли онлайновое решение?

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

        Онлайновое.
        Есть еще онлайновое для n <= 105, но я такое писать не умею :D

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

          А как 4 операцию делать?

          Для 1/2/3 операций я копирую и изменяю битсет полки. Для каждой полки есть вектор с парами времен эвента и ссылкой на номер последнего битсета.

          При 4 запросе я для каждой полки ищу lower_bound-ом по k номер соответствующей версии полки и добавляю пару с текущим временем и найденной версии в каждую полку — дает TL 28.

          • »
            »
            »
            »
            »
            »
            8 лет назад, # ^ |
              Проголосовать: нравится -9 Проголосовать: не нравится

            А зачем там lower_bound? Можно для каждой версии шкафа итеративно присваивать номер, тогда так и обращаться в k-тый экземпляр.

            У меня на абсолютно каждую версию хранится вектор индексов полок, входящих в данный шкаф, и отдельно еще массив с суммой единиц на полке (да, я не умею в битсеты)

            http://mirror.codeforces.com/contest/707/submission/20009104

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

              Сделал почти также. Превысил ограничение по памяти. 20012349

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

                Да, там надо довольно аккуратно писать. И если в векторе со шкафами меньше интов взять ничего не получится, то в полках достаточно векторов чаров/булов или битсетов, там ведь только нули и единицы хранятся. Так в худшем случае должно быть около 490 мб.

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

                  Точняк. Совсем забыл, что полки в bool надо сделать. Всё прошло. 20012931

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

        Есть онлайн решение, реализовал персистентное дерево отрезков по строкам. А саму строку храню в bitset, это хорошо работает т.к. bitset можно ксоритьБ а также есть полезная для данной задачи функция count(). Оценка сложности q*log(n)*m/32. Решение

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

      Сделал, как описано. Получаю TL на тесте 70 либо ML на тесте 47. Для поддержания полок пробовал разные структуры:

      vector <bool>20155806

      vector <char>20150187

      bitset20150105 — код с комментариями UPD:20157774

      struct state{ bool val[MAXN]; }20154885

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

Кто может объяснить, может ли путь до пекарни пролегать через другие города в задаче B? А если нет, как трактовать условие "между городами b и s существует путь по дорогам суммарной длины x (если путей несколько, Маша вправе выбирать, какой именно путь будет использован)."?

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

    Может, конечно, но лучший вариант всегда будет напрямую от склада до пекарни, то есть по одной дороге не проходя через другие города

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

Можно объяснить разбор задачи D и Е поподробней? А то прочитал и появилось чувство, что тупой)) Можно авторский код?

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

    Действительно, неплохо бы было привести ссылки на авторские решения. Тоже ничего не понял из разбора последних 2 задач :(

    Хочу поблагодарить автора за интересные задачи, но такое ощущение, что разбор писался с где-нибудь в переполненном автобусе на какой-нибудь старенькой nokia.

    Так не годится, если уж делать разбор, то делать круто, а то больше похоже на то, посмотрите какой я крутой.

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

У меня одного написано "Разбор недоступен"?

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

Либо я чего-то не понял, либо я совсем по-другому решил задачу Д. Как минимум в обоих решениях я вижу надпись "дерево версий", в то время как у меня хранится лишь одна версия шкафа всегда. Как я этого добился? Я построил граф на запросах и обошел его ДФСом (вот этот момент совпадает с первым решением). В графе в вершине хранится следующая операция для выполнения, но в одной вершине i так же будут хранится все операции вида "4 i". Тогда при обработке одной операции я вычисляю для неё ответ, вызываю ДФС из следующей операции, а по возвращении из ДФСа откатываю изменения (благо операции позволяют это сделать). Таким образом, операции выполняются не в хронологическом порядке, и каждая операция выполняется два раза (прямая и обратная), но всё это позволяет храниться лишь одну версию шкафа. Так же, для того чтобы не мучится с деревом отрезков и проталкиванием операции "переворота полки", я храню одну полку в len = 20 числах типа long long (по 50 бит в одном числе), что позволяет мне за О(1) делать операции поставить/убрать книгу и за O(len) — "перевернуть полку". Итого: O(q * len) времени и O(n * len + q) памяти.

Код решения

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

    Этот граф и имеется ввиду под определением "дерево версий"

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

      Для меня это немного не интуитивное определение, учитывая, что сами версии мы не храним, а лишь несколько раз в них попадаем, выполняя операции. Но, скорее всего, я просто первый раз столкнулся с таким определением.

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

    На самом деле переворачивать можно за O(1), так как нам нужно только количество книг на полке, а не их координаты. Итоговая асимптотика будет O(q).

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

      Количество книг можно узнать за О(1) — да, но что делать, если после этого нужно поставить/убрать книгу, а у нас уже нет валидной полки с расстановкой книг? Хотя тогда можно заморочиться и считать количество переворотов, вычислять стоит сейчас книга всё-таки или нет и ставить/убирать, если надо.

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

        У нас есть перестановка, но она либо прямая, либо инвертированная. Значит нужно дополнительно хранить для каждой полки ее состояние. Пример для запроса первого типа: 1) если полка прямая и место не занято, то увеличиваем ответ, иначе ничего не меняем, 2) если полка инвертированная и место занято (так как состояние самой полки мы не меняем, а только флаг), то увеличиваем ответ, иначе нечего не делаем.

        Теперь, как пересчитывать ответ, когда идет переворот, для этого дополнительно будем хранить количество занятых мест на полке. И тогда когда переворачиваем полку, ответ меняется так: ans = ans - b[xi] + (m - b[xi]), b[xi] = m - b[xi].

        Моё решение: 19996879.

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

          На самом деле я у себя пересчет ответа делал именно так изначально (у меня даже массив сумм так же называется — b). А переворот полки я совершал только чтобы потом легче можно было выполнять операции 1 и 2 типа.

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

            В принципе, такой подход достаточно популярен, когда нам не нужны сами состояния, а только какая-та функция на ними.

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

Поясните, пожалуйста, решение задачи D (решение №1), а то не понятно :(

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

    Выше мой большой комментарий описывает подробно это решение.

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

Ещё в задаче D можно было не долго думать, а написать персистентное дерево отрезков, упорядочив шкаф как линейный массив.. =)

А в задаче Е — считать все запросы, потом для каждой пары "гирлянда — ASK-запрос" посчитать с помощью дерева Фенвика сумму лампочек на прямоугольнике запроса, а потом, отвечая на запросы, только добавлять или нет значение предпосчитанной суммы в зависимости от того, включена гирлянда или нет.

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

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

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

    персистентное дерево отрезков с проталкиванием

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

Объясните Сшку, пожалуйста

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

    Разница между квадратами двух соседних чисел всегда есть нечетное число. Например, 4 - 1 = 3, 9 - 4 = 5 и т.д. Можно также заметить, что все разницы образуют арифметическую прогрессию. Благодаря этому, можно достаточно легко от разницы прийти к самим числам и обратно. Если разница равна нечетному A^2, то первое число будет A^2/2, а второе число на единицу больше первого. Например, A = 9, B = A^2/2 = 40, C = 41. Если же A — четное, тогда и разница A^2 — четная, то можно поделить А на максимальную степень двойки, найти ответ таким же образом и домножить его на эту степень. Исключением являются разницы для A = 1 и A = 2, для них найти ответ нельзя. А так же стоит отметить случай, когда А уже равна степени двойки (деление на максимальную степень двойки приведёт нас к 1, для которой ответ найти не получится), в этом случае, поделив А на степень двойки X, надо получить А = 4, а для катета равного четырём существует Пифагорийская тройка (3, 4, 5). В этом случае ответ будет соответственно 3 * X и 5 * X. Данное решение немного отличается от описанного в разборе.

    Код решения

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

      Это решение для катета, а что если ввести длину гипотенузы?

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

        Любой отрезок длиной больше 4-х может быть как катетом, так и, возможно, гипотенузой.

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

Can you please give the tutorial for Problem C — Pythagorean Triples?

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

    n = 1, 2: There are no solutions (easy to prove)

    n is even:

    n is odd:

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

      Do you have a proof for the formula ?

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

        You can prove it by induction.. Check the base case by considering the case that sum of two sides of triangle is greater than the third side. This will give you n>1 for odd 'n' and n>2 for even 'n'.

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

        You can directly substitute and check using (a + b)2 = a2 + b2 + 2ab formula.

        No need of induction.

        For instance

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

      how can i come with such a formula if i didn't know it before ?

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

        Actually you can figure it out easily. You see that n²=m²-k²=(m-k)×(m+k), so you need to find a way to present n² as a×b with (a-b) is even. You will always find a and b if n is odd and larger than 1, which is 1 and n². If n is even and n is larger than 2 then how about 2 and n²/2. Easy as that, huh?

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

        The second formula for odd numbers is easier to see in the following form —

        (k)^2 + (2k + 1) = (k + 1)^2

        If n is odd, it's square is also odd ... so** n^2 = 2k + 1**, and the equation is re-written in terms of n.

        If n is even ... i.e.** n = 2m**, then** n^2** is also even ... so n^2 = 4k .. a multiple of 4. Using that observation,

        then

        (k — 1)^2 + (4k) = (k + 1)^2

        Again the equation is re-written in terms of** n**.

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

    consider a^2 = b^2 + c^2 (PT)

    now we are given the cathetus (any of the two sides other than hypotenuse) let c = n then -> n^2 = (a-b)*(a*b) [a^2 — b^2]

    check yourself that either (a-b) and (a+b) both are even else both are odd

    from the above eqn (a-b) and (a+b) are factors of n^2

    simplest -> if n is odd let (a-b)=1 and (a+b)=n^2

    if n is even let (a-b)=2 and (a+b)=n^2/2

    solve these and u will get values for a and b :) but for n<=2 no ans exists so print -1 :)

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

      Brilliant explanation .

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

      why did you assume that if n is odd you put a-b =1 why 1 not any odd number .and the same if n is even ?

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

        I said that's the simplest.... Plus u need a-b to be a factor of n^2 and 1 is a factor of every number that's why a-b=1 same goes if n^2 is even

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

      Your_dad, actually we are given either cathetus or hypotenuse. Is there always exist a Pythagorean triple in which given n represent cathetus? How can we prove that?

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

        Let n = 2k where k > 1. Consider the Pythagorean triple obtained by scaling (3, 4, 5) by .

        Now suppose n has some odd prime factor. Every odd prime p is the difference of two consecutive squares. Let x be such that (x + 1)2 - x2 = 2x + 1 = p. Thus, (p, 2x(x + 1), x2 + (x + 1)2) is a Pythagorean triple. Scale it by and you obtain a triple that has n as a cathetus.

        Thus, every integer n > 2 is a cathetus of at least one right triangle.

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

          How to prove that for n <= 10^9 and n is a cathetus, there exists c <= 10^18 where n^2 + x^2 = c^2?

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

            For the case of 2k, it's trivial, so suppose n has an odd prime factor p = 2x + 1 as in my previous comment. We can show that my scaled right triangle will be small enough for the problem:

            As for the hypotenuse:

            Note that in the last step, the reason $x+2 \leq p$ is because x ≥ 1 since p is at least 3.

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

    [http://www.codeforces.com/blog/entry/46681] try this:P

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

Problem D solution no.1

Does that mean if there's op is '4', then the tree contains a cycle?

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

    No. in the case of 4 x , you don't attach the node i-1 to the node x , you attach the node i to x.( i will be the another children for x )

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

Nice contest. Can you elaborate more the second solution of D ?

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

    Note that for operation 1~3 we will only change one line at a time. So there are at most 10^5 different lines. We can use array/bitset to maintain these lines. Lets call this array/bitset lines[]. We also need to know after each operation, where these lines are stored. So we need a new array position[][]. position[op][i] means after the op-th operation, the status of the i-th line is stored in lines[position[op][i]].

    When we use operation 1~3, we just add a new line to lines[]. And after each operation, we will need to update position[][]. If we use operation 1~3, only position[op][i] will change to the newest added line. If we use operation 4, we just need to iterate through all lines, and let position[op][i] = position[x][i].

    You can also see my submission for details (I use a bitset to maintain lines[]) 20015649

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

      goto is not good,you can use continue instead

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

      I guess we can just use string here instead of bitset. Bitset has a little more overhead.

      When using string, we could add another field inverted that basically keep track of # times operation 3 applied % 2. inverted == 1 means every bits in the string are inverted, otherwise not.

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

      Your complexity is O(n*q). This means O(10^8) worst case. How can this fit in 2 seconds?

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

        I'm not quite sure about the speed of the judge server, but the following code can be executed within 1 second on my laptop (just a normal laptop, not a very good one).

        #include <stdio.h>
        #include <time.h>
        int main()
        {
            int i;
            for(i=1;i<=300000000;i++);
            printf("%d",clock());
            return 0;
        }
        

        So I think O(10^8) can be executed within 2 seconds.

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

        I guess if he use memcpy instead of coping by loop it would be faster. Despite the fact that memcpy also loops it's so much faster.

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

      I did as you told, but I've got TL — 20157774

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

Problem D. also has an online persistant segment tree solution. 19996544

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

Another solution to problem E.

Note that the data is delivered all at once (offline). We can precalculate the sum of the happiness value of each garland in each rectangle given in the "ASK" operation (using two-dimentional Binary Indexed Tree/Fenwick Tree). Then for every "ASK" operation we just need to enumerate all the garland and see if it is on. If the garland is on we can add the precalculated value to the answer.

The time complexity is O(nm(log(2000))^2). You can see my submission for detail 20021444

»
8 лет назад, # |
Rev. 5   Проголосовать: нравится +8 Проголосовать: не нравится

Моё решение по Е: построим дерево Фенвика для каждой гирлянды по отдельности. Переключение гирлянды будем выполнять за O(1), а поиск ответа за O(qask * k * log n log m). Теперь встаёт вопрос лишь о том, сколько памяти будет занимать одно дерево Фенвика. Разумеется, если на него выделить O(n*m) памяти, то суммарный объём памяти превысит 1 гигабайт в несколько раз. Поэтому можно сжать область для построения дерева до габаритных размеров гирлянды. Допустим, все гирлянды представляют из себя прямые линии, то тогда на одну гирлянду будет уходить O(len) памяти, что приемлемо. Если же представить гирлянду в виде квадрата, то потребуется тот же объём памяти O(sqrt(len)*sqrt(len)), что так же приемлемо. Но если представить гирлянду в виде "змейки" (одна клетка вправо, одна вверх и т.д.), то потребуется O(len/2 * len/2) памяти, что уже очень много. Но встаёт вопрос о том, сколько максимально может быть таких "змеистых" гирлянд. Расположим такие гирлянды следующим образом:

Очевидно, что таких гирлянд может быть по крайней мере половина из всех возможных. То есть объём занимаемой памяти составит O(len/2 * len/2 * k/2), а учитывая, что требуется хранить числа типа long long, это будет около 8 гигабайт.

Перед тем, как писать это решение я сразу подумал о том, как его оптимизировать. Так как для змеистых гирлянд очень много элементов дерева Фенвика будут равны нулю, то можно построить это дерево на структуре map, благодаря чему мы не выделим лишней памяти. Но тогда во время работы добавится третий логарифм. Второй способ оптимизировать — построить дерево отрезков, только не в простой форме, а в виде структуры данных, в которой хранятся ссылки на левого и правого сына. Если в какой-то вершине сумма равна нулю, то нам не нужно спускаться ниже по дереву отрезков, и, более того, не требуется хранить дальнейшее разбиение.

Решения с описанными оптимизациями я написать не успел потому, что моё первоначальное решение, на моё удивление, зашло, потребив всего 36 мегабайт памяти. Теперь вопрос к автору задач: есть ли тесты с подобными "змеевидными" гирляндами?

Код решения

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

    Чтобы сэкономить память можно было делать задачу в оффлайне. После построения дерева Фенвика для i-ой гирлянды мы сразу выполняем все запросы, которые нам потом понадобятся. После этого текущее дерево нам уже не нужно и мы удаляем его, таким образом в памяти хранится только одно дерево.

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

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

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

I know this is your first editorial but I think editorials should be more detailed, editorials should be 'editorials' if that makes any sense. Thanks for the round.

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

Can anyone add the solution to the second problem? My code is http://ideone.com/fOzg7O. Please tell me where I am wrong.

  • »
    »
    8 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    1. Your solution gives WA, because you create arrays u1[m], v1[m], l1[m] of size m. But following cycle can add 2m edges. So this solution works correctly.

    2. Now we have TLE. That is because your solution works at least in O(m*k). You can see 19989181 — my contest submission, which works in O(m + k).

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

There is another solution to C , which gives you all pythagorean triplets in O( 500* sqrt(side ) ) . 20008793

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

Can someone please explain the editorial solution of E? I could not understand it properly. What is 'concrete garland' and 'extreme point'? How are we handling 'garland which lies entirely within the request'?

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

    There are only 2000 ASK queries. For each ask query let us precompute for each garland the sum it will contribute if this garland was on. This can be done by a 2-D BIT. This will take time equal to O(ASKQ * K * logN * logM).

    Then for each switch query just keep an array which will denote whether each garland is currently on or off. For each ask query, iterate over all garlands, if it is on, add to the answer the previously computed sum.

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

      I understood this one. But is this the one explained in the editorial? I don't think so. Please correct me if I'm wrong. :)

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

    Its almost like he doesn't want us to understand what he wrote facepalm

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

    The solution in editorial uses prefix sums of values in garland to find answer to a query. Whenever a garland enters the frame, subtract prefix sum from answer, and whenever a garland leaves the frame, add prefix sum to answer. Also, for a garland ending inside the frame, add the prefix sum of its end to the answer. Do all these operations only for "on" garlands.

    There will be O(n+m) such entries and exits, hence time complexity: O(2000 * (n + m))

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

In solution for B I believe that this If there is such a pair of cities, print -1. should be rewritten to ..if there is NO such pair..

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

Someone please explain the editorial of E

  • »
    »
    8 лет назад, # ^ |
    Rev. 3   Проголосовать: нравится +9 Проголосовать: не нравится

    In problem E. there are at max 2000 ASK queries. And k<=2000. So for each ASK query basically we are calculating our answer separately for each garland. Now we arrive at two cases :

    1. When the entire garland is in our rectangle (the one in query) This can be checked in O(1) for all the garlands by storing the extreme points . That is storing the topmost, leftmost,rightmost, bottommost. If all these points are inside the boundary, then we simply add the sum of all the values in garland to our answer.

    2. If some part of the garland is inside and rest is out, then at least one of its lighthouse must be present on the boundary. While taking the input, for each garland we can number all the lightbulbs in the order of input (Consecutive in the grid), and we can make an array of pair of integers where for each cell we store the garland number and the index of the lighthouse. Now we need to iterate through the four boundaries and we need to store the indeces where some garland exits or enters the rectangle. This can be easily done. Refer to my implementation. Now with this information we need to calculate the sum of lightbulbs in the rectangle, which can be done by storing the prefix sums for each garland.

    Time Complexity : O (q* (n+m+klogk)) where q<=2000 Here is my implementation : 20021555

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

      Got it!

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

      You are also sorting the positions for each garland.That would bring another logn.

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

      Since the maximum length of a garland is $$$2000$$$, we can use counting sort instead of ordinary sort and bring the complexity to $$$O(ASK * (n + m + k))$$$.

      Also, when checking for garlands that lie completely inside, we don't need to check extreme points (minX, maxX, ...) as the editorial said. Instead, we can take any point of the garland and check if it lies inside the rectangle. Since we have checked all border cells, if any point of the garland lies inside the rectangle, then it has to lie totally inside. We can conveniently check the last point, since we need to check it anyways.

      This is my implementation 126593034. Sadly, in this problem, solutions with $$$log$$$ are indistinguishable from linear ones, and even $$$log^2$$$ ones can pass.

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

What's the time complexity of problem E.

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

Can you explain about problem D using dfs

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

    Let's construct graph, where every vertex is state of our bookcase. Initialy we have one vertex corresponding to the initial state of bookcase. Let's process all queries. We will create new vertex every time we find queries of type 1, 2, 3. Also we make new edge from current vertex to the new one. On queries of type 4 we just change our current state(without changing the graph). Then we travel across graph with dfs and apply every change of bookcase written on the edge.

    Sorry for my english. Here is the code. I hope it will help.

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

Worst editorial ever !!

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

Why there isn't any editorial for C ?!

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

Thanks for the great round.

Would like to know if anyone could do O(q) or anything better than O(qm) online solution of problem D?

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

    Yes there is an online O(qlogn) solution using persistant segment tree. 19996544

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

      Thanks for the tips!

      I found a pretty good explanation of persistent segment tree here for anyone might be interested. If you know this the solution could be super straightforward.

      Note that it's actually a simplified persistency, compare to real persistency like partial persistency and full persistency. There is a pretty good youtube video course that would walk you guys through those ideas if you are interested, see here.

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

      how did you handle range updates?

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

        Lazy propogation.

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

          yeah i tried lazy propagation but i am stuck in a point.Point updates are clear like

          Point updates for a particular query means that we have to change only log(n) nodes in path from root to leaf so for q queries space complexity would be n+qlog(n) but for the case of range updates i would keep a lazy value at each node but the problem i am facing is that the node to be updated would be representing some range so to change it would mean recreating the whole structure beneath it which be be too much costly considering the fact that there might be more range updates in the queries.Can someone suggest how to implement this?

          I implement lazy propagation like this in normal segment tree first when i need to update a range i update the node representing the node and if it is not a leaf node i pass the lazy update to its two children but here if i just create a new node and pass the lazy value down this will contradict with some other k used before.

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

In Problem E, there is another offline solution which uses persistent segment tree. Note that 2d range query can be done in O(log n) with a persistent segment tree. So for each garlands, add its lightbulbs' weights to their coordinates to the persistent segment tree. Now for each ASK queries, we can determine how much the garland will affect to the answer by summing the rectangle area. After calculating them, we follow the queries again, turn on/off garlands, and calculate the answer. Time complexity is O(q+k(len log len + len log 2000 + s log 2000)+ks). (s is the number of ASK queries)

http://mirror.codeforces.com/contest/707/submission/20108841

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

    Can you help me regarding range updates in persistent segment tree referring to my above comment?

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

Написал все возможные решения по Е и вот что получилось:

Моё первоначальное решение с деревом Фенвика, которое в теории вообще не должно работать — 1.3 с и 36 мб.

Первоначальное решение оптимизированное структурой map — Time Limit.

Первоначальное решение оптимизированное деревом отрезков без хранения границ — 1.6 с и 150 мб.

Первоначальное решение оптимизированное деревом отрезков с хранением границ — 1.7 с и 190 мб (странно, что работает дольше...).

Решение с преподсчетом ответов на все запросы для каждой гирлянды через дерево Фенвика — 1.9 с и 110 мб.

Решение из разбора (наговнокодил немного) — 2.2 с и 95 мб.

Вывод: надо писать то, что в теории не работает, и быть может оно отработает быстрее и потребует меньше памяти, чем прочие решения.

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

Тыкнул по первому попавшемуся (полному) решению 20009296. И сразу возник вопрос: как вообще так?

1е6 запросов * 2000 лампочек * (еще какая-то сложность, логарифм, вероятно) = PROFIT

А авторское решение не заходит..

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

I write a solution for problem C in my blog. If you can't solve this problem, check out this link!

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

I'm having difficulties with question B — Bakery. Can someone help me with what i'm doing wrong

https://mirror.codeforces.com/contest/707/submission/78816637

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

Чутка поздновато но я хотел бы попонятнее обьяснить задачу С.

Если выписать все квадраты получим последовательность 1, 4, 9, 16, 25, 36, 49....

Разность между соседними элементами 3, 5, 7, 9, 11, 13, 15, 17...

Для нечетных:

Таким образов всегда существует решение для нечетных n, так как n * n тоже нечетно и мы можем найти эту разность следующим образом: так как каждый раз разница между элементами возрастает на 2 то мы можем найти первое число возведя n в квадрат и поделив на 2 следовательно второе число n * n / 2 + 1.

Для четных:

Посмотрим на разность между двух элементов которые находятся на расстоянии 2 друг от друга:

получим: 8, 12, 16, 20, 24, 28, 32, 36...

Следовательно для любого четного можем найти разность квадратов.

Как найти эту позиции в нашей последовательности? каждое четное число это сумма двух нечетных 8 — 3 + 5, 12 — 5 + 7 и так далее а как найти например 3 мы уже знаем. Итого ответ n * n / 4 — 1 и n * n / 4 + 1