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

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

Здравствуй КФ! Давно хотел узнать, как можно решить такую задачу : 1. Дан массив a[] из n элементов 2. Есть Q запросов : a) L, R, Value : Со всеми элементами массива на отрезке [L .. R] сделать следующее : mas[i] = max(mas[i], Value) b) L, R Вывести сумму элементов на отрезке [L .. R]

Давайте обсудим варианты решения :)

  • Проголосовать: нравится
  • +3
  • Проголосовать: не нравится

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

Какие ограничения? Числа до 10^9?

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

Неправильное решение

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

    /

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

    По-моему не получится, как вы будете мёрджить 2 дерева по явному ключу, если у них значения в левом не всегда меньше, чем в правом?

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

      Почему не меньше?

      Мы расспилитили дерево на <=value и >value. Потом присвоили левому value. Получили два дерева =value и >value. Вроде все ок...

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

        Я про декартовы деревья, которые хранятся в каждой вершине.

        Допустим, пришёл запрос в корень "убрать все меньше 2", вы их убрали из treap[1], как-то даже может быть протолкнули дальше. После этого запрос "убрать все, меньшие 5" для правого поддерева (treap[3]), оттуда тоже как-то убрали. Теперь надо что-то сделать с treap[1], у него элементы в рандомных позициях стали равны 5. Смёрджить treap[2] и treap[1] не получится.

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

Будем хранить в каждой вершине ДО отсортированный по убыванию список чисел, которые эта вершина контролирует. Когда приходит запрос на обновление делаем следующее: находим те вершины, которые полностью находятся внутри диапазона на обновление (минимальное множество) и начинаем выкидывать числа из списка, которые меньше заданного числа обновления. Как только мы закончим ответом для данной вершины будет сумма чисел в списке + последнее число в списке оставшееся количество раз (сколько нужно) + обновляем если необходимо число, которое нужно пушить вниз (на самом деле это просто будет последнее число в списке).

Получается каждое число будет в ДО не более чем в log(n) вершинах и столько же раз может удалиться. Итоговая ассимптотика O((n + q)log(n).

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

    Здесь не будет той же проблемы? Пусть из корня выпилили все, меньшие 3, дальше всегда это будем проталкивать. Потом откуда-то из глубокого места убрали все, меньшие 5, допустим правильно передали сумму наверх. Теперь вписок в корне содержит элементы, которых уже нет. Теперь из корня опять что-то удалили, как вы будете обновлять сумму в корне дерева?

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

      Тут придется хранить число и указатель на ячейку для этого числа (не значение этого числа, а номер запроса, для запросов с одинаковым значением), указывающее выпилили ли мы это число или нет. Когда мы из вершины удалили число, мы указатель в этой вершине пометили, что оно мертвое. Теперь сумму в предках посчитаем верно, но когда начнем выпиливать, то корректно выпилим. То есть выпилим все что меньше значения, затем все мертвые на хвосте. Как то так.

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

        Я не понял, как мы в корне узнаем, что где-то глубоко удалилось какое-то число (чтобы в корне пометить, что оно мёртвое).

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

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