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

Автор Iura_Shch, история, 6 недель назад, По-русски

Привет, Codeforces!

Мне довольно сильно нравятся всякие корневые, поэтому я начал думать в их сторону и придумал 3д-мо в онлайне(почти). 

Задача: дан массив из N чисел, Q запросов(в онлайне) к этому массиву и число K. Каждый запрос принадлежит одному из двух видов:

update pos val — присвоить a[pos] значение val; get L R — узнать количество чисел, встречающихся хотя бы K раз на отрезке с L по R.

Решение: (далее / везде будет обозначать деление с округлением вниз)

Назовем ящиком следующую структуру: индексы L R(начало и конец текущего полуинтервала, в 0-индексации), массив подсчета(если он нужен) и ответ(res). Пусть C - кубический корень из N.
Теперь заведем C^2 ящиков и зададим им следующие границы: у ящика i(в 0-индексации) L = (i / C) * (N / C), R = (i % C) * (N / C). Если R <= L, то просто игнорируем данный ящик. Заведем массив подсчета cnt для этого массива и насчитаем ответ(в данной задаче границы двигаются за O(1), ведь надо уметь добавлять число в множество и удалять из него, а это cnt[X] += 1 и cnt[X] -= 1 и res += 1 и res -= 1, если cnt[X] перешло через K).
Как отвечать на запросы? Для первого типа переберем все ящики и для тех, у которых выполняется L <= pos < R обновим ответ. Запрос выполнен за O(C^2). Для второго типа возьмем отрезок с индексом i = (L / (N / C)) * C + (R / (N / C)) и сдвинем границы. 

Пусть L* — левая координата ящика. Тогда L* = (((L / (N / C)) * C + R / (N / C)) / C) * (N / C). R / (N / C) <= C, тогда L* = (((L / (N / C) + B) * C) / C) * (N / C), B = 0 или B = 1, L* = L + B * (N / C). Тогда расстояние от L* до L не превосходит B * (N / C), а значит не превосходит N / C = C^2, аналогично для R, значит мы найдем ответ за O(C^2). Итоговая асимптотика: O((N + Q) * C^2) времени и O(N * C^2) памяти. Возьмем теперь любое С. Итоговая асимптотика: O((N + Q) * max(N / C, C * 2)) времени и O(N * C^2) памяти. Иногда может быть полезно брать разные C, так как при уменьшении C уменьшается затрачиваемая память. Данный алгоритм решает и другие задачи, где в оффлайне работает 3д-мо. Единственная проблема состоит в сжатии координат. Без него время работы домножается на константу map или какой-нибудь хеш таблицы. Но, например, в задачах про mex нас не интересуют числа, большие n, а в задачах про различные числа можно сжимать в онлайне, ведь важно только разным присваивать разные значения.

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

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

Автокомментарий: текст был обновлен пользователем Iura_Shch (предыдущая версия, новая версия, сравнить).

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

Автокомментарий: текст был обновлен пользователем Iura_Shch (предыдущая версия, новая версия, сравнить).

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

Я может быть что-то не понимаю, но ведь предложенную задачу решает дерево отрезков, причем с более лучшими оценками как по времени, так и по памяти (сложность по времени будет $$$O ((n+q) \log^2 n)$$$ вместо вашего $$$O ((n+q) n^{\tfrac{2}{3}})$$$, по памяти -- $$$O (n \log n)$$$ вместо предлагаемого вами $$$O (n^{\tfrac{5}{3}})$$$). Поэтому возникает вопрос, чем оно лучше? Какую задачу оно решает лучше чем другой уже известный алгоритм?

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

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

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

      Так может стоило привести пример, где не существует другого алгоритма, решающего задачу стольже эффективно? Иначе возникает вопрос зачем это нужно.

      P. S. Простой поиск в Google наводит на статью https://codeforces.net/blog/entry/83630 от некого pakhomovee. Следовательно, все рассказанное вами уже известно и никакой новизны не представляет(

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

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

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

          Ложь, вот задача на мо с изменением в точке и онлайн запросами, не являющаяся примером, где не существует другого алгоритма, решающего задачу столь же эффективно:

          Дан массив чисел $$$a_1, \ldots, a_n$$$. Изначально все $$$a_i = 0$$$. Приходят запросы в онлайне:

          $$$1\ l\ r\ k$$$ — посчитать количество нулей на отрезке среди чисел $$$a_l, \ldots, a_r$$$.

          $$$2\ i\ x$$$ — присвоить $$$a_i = \frac{x}{x} - 1,\ x \neq 0$$$.

          Задачу можно решить с помощью мо за $$$O(n^\frac{5}{3})$$$, но очевидно, что есть решение за $$$O(n)$$$: положить болт на запросы второго типа и ответом на первый всегда будет $$$r - l + 1$$$.

          Вывод: автор коммента (Iura_Shch) pussiмяч.

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

Auto comment: topic has been updated by Iura_Shch (previous revision, new revision, compare).

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

Very nice blog! I'm so surprised I never saw this idea before...

I hope you take this in a positive way to improve your blog so that others wont just click off your blog

  • use proper markdown and latex formatting
  • use images and concrete examples. Humans usually think about specific examples before abstracting. I took quite long to understand what "let L = (i / C) * (N / C) and R = (i % C) * (N / C)" was trying to do, but if you added something like, for example if $$$N=27$$$, we should store info on ranges $$$[1,9],[1,18],[1,27],[10,18],[10,27],[19,27]$$$. But of course a diagram would be much clearer)