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

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

Пацаны, расскажите пожалуйста, я баян придумал или нет?


Задача простая: m запросов, вывести k-ю порядковую статистику массива a[n] на отрезке [l,r]. 
n ≤ 105, m ≤ 105
Сложность: n· log(n) препроцессинг, log2(n) на запрос.

Что делаем:
1) Сортируем массив в виде пар (ai, i), сначала по значению, потом по индексу.
2) Строим n-штук persistent segment tree, где на i-м шаге добавляем в дерево отрезков индекс элемента, который находится по i-му индексу в отсортированном массиве пар.
3) Бинпоиском находит нижнюю границу i, где в дереве отрезков i sum(l, r) ≥ k.
4) Это и есть наш ответ, выводим число.
  • Проголосовать: нравится
  • +16
  • Проголосовать: не нравится

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

K-ю порядковую статистику на отрезке за O(log^2(n)) на запрос можно считать неперсистентным деревом отрезков. А при помощи персистентного можно досчить асимптотики O(log(n)) на запрос
  • 14 лет назад, скрыть # ^ |
     
    Проголосовать: нравится 0 Проголосовать: не нравится
    А как второе делать, расскажите пожалуйста.
    • 14 лет назад, скрыть # ^ |
       
      Проголосовать: нравится +26 Проголосовать: не нравится
      Представим, что на плоскости отмечены точки с координатами (i, a[i]). Тогда ответом на запрос будет k-я по высоте точка в вертикальной полосе, края которой соответствуют границам запроса. 

      Сожмём координаты и построим персистентное дерево отрезков на сумме, добавляя в позицию trans(a[i]) единицу, где trans(a) - значение а в сжатых координатах (должно получиться такое дерево, что итоговая версия будет возвращать кол-во элементов, значения которых после сжатия лежат в диапазоне от l до r). Теперь, за логарифм спускаясь из корня соответствующей версии дерева, мы умеем отвечать на запрос о k-й порядковой статистике на префиксе массива. Так как деревья отрезков для разных префиксов изоморфны, то дерево для вертикальной полосы, соответствующей отрезку запроса [L; R], можно получить, вычитая из значения в каждой вершине дерева версии R значение в соответствующей вершине версии L-1. Так как нам интересны значения только в O(log(n)) вершинах этого дерева, то не станем строить его явно, а просто будем спускаться по обеим версиям и получать нужные значения в несуществующем дереве для полосы от L до R.

      P.S. Кривое вышло объяснение, но без листочка, на котором можно что-нибудь схематично изобразить, лучше не могу.
14 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится
Northern Subregion 2004. Problem K.
http://neerc.ifmo.ru/subregions/northern.html
14 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится
Можно за делать, строя дерево отрезков, в каждой вершине которого - отсорченный подмассив. Занимает памяти, такая задача есть и на spoj.pl.
В обсужениях этой задачи Robert Gerbitz говорил, что умеет решать за с препроцессом .
14 лет назад, скрыть # |
Rev. 5  
Проголосовать: нравится -9 Проголосовать: не нравится

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

P.S. кст, с помощью декартова дерева, можно эту задачу даже on-line решать

P.S.S. нельзя, я ошибся, вернее все, что я написал выше-неверно
  • 14 лет назад, скрыть # ^ |
     
    Проголосовать: нравится 0 Проголосовать: не нравится
    Хм.. два вопроса. 
    1) как
    2) а почему построение не за линию?
    • 14 лет назад, скрыть # ^ |
      Rev. 2  
      Проголосовать: нравится 0 Проголосовать: не нравится

      1) ну поступает запрос на отрезке [L;R], сплитим по L, по R, получаем три дерева: первое содержит элементы [1..L-1], второе [L;R], третье [L + 1;R], теперь второе сплитим по К, берем самую правую вершину, отвечаем на запрос и merg'им деревья

      2) ну за линию тоже можно, просто я пишу  за NlogN, за линию ни разу не писал

      P.S. забудьте, я накосил

14 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится
Ну тогда уж до кучи это решается корневой с линией памяти и времени (я видимо умею еще и за аккуратным разбиением кусков. И мне кажется что это будет быстрее log^2 и log^3, за персистентный log не уверен. наверное какая-то оптимизация этого.
14 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится
Я может туплю... А почему нам не отсортировать массив и за 1 время говорить l+k-ю статистику (просто взяв значение A[l+k])?
14 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится
Вообще, эта задача была этим летом на сборах в Петрозаводске в контесте команды Тавриды. При этом, были следующие ограничения: N<=450000, количество запросов <= 600000, TL 4 секунды. Вроде как ничего, кроме персистентного дерева с ответом за logN на запрос, не проходило. Авторское решение совпадает с решением из поста Malinovsky239.
14 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится
Можно же решать обычным двумерный деревом интервалов с fractional cascading, будет O(nlogn) памяти и O(logn) ответом на запрос (и думать особо не надо).
14 лет назад, скрыть # |
 
Проголосовать: нравится 0 Проголосовать: не нравится

offtop:

скажите, как решать задачу "найти количество различных чисел на отрезке"?