SPARSE TABLE




скачать

SPARSE TABLE (разреженная таблица)
 
Sparse Table – структура данных, которая позволяет отвечать на запросы типа “найдите значение функции на неизменяемом массиве на отрезке [L;R]” и при этом занимает О(1) времени и О(n*logn) памяти, где n – размер массива.
 
Sparse Table (далее ST) корректно работает только с идемпотентными функциями*
 
Описание структуры:
 
Перед рассмотрением самого ST рассмотрим некоторый факт, на основе которого заключается весь смысл ST.
 
“Отрезок любой длины можно покрыть двумя отрезками, длины которых являются степенями двойки и при этом не превосходят длины отрезка, который необходимо покрыть” (можете доказать это сами или просто поверьте, что это правда).
 
Примеры:
 

В чем идея ST: давайте предподсчитаем нужную функцию в массиве на всех подотрезках, длины которых являются степенями двойки и далее будем пользоваться ими, чтобы отвечать на запросы.
Можно заметить, что некоторые подотрезки перекрываются дважды. Именно поэтому ST работает только с идемпотентными функциями.
 
Построение ST:
Пусть F() – функция, которую мы считаем на нужном массиве.
Заведем массив d[logn][n], где n – размер массива.
d[i][j] – F() на подотрезке исходного массива, длина которого 2^i и начало в j.
Очевидно, что мы знаем F() для подотрезков длины 2^0 т.е. 1 – это сами значения массива.
 



Далее будем подсчитывать значения следующим образом:
Пусть мы сейчас хотим узнать F() для длины 2^i. Мы уже посчитали значения для подотрезков длины 2^(i-1), а 2^i = 2 * 2^(i – 1), поэтому нам достаточно взять F() уже посчитанных значений двух подряд идущих подотрезков длины 2^(i-1) и начинающихся с текущей позиции.

Например:
Сейчас мы подсчитываем F() на подотрезке длины 2 и начинающегося с позиции 0. Мы уже знаем все значения на всех подотрезках длины 1. Поэтому нам достаточно взять F() с подотрезка длины 1 и начинающегося в позиции 0 и подотрезка длины 1 и начинающегося в позиции 1. Это и будет F() пары, начинающейся в позиции 0. То есть для каждой пары мы считаем через два подряд идущих единичных элемента, для каждой четверки через две подряд идущие пары и т.д.
 




Асимптотика построения – О(n*logn).
 
Ответ на запрос:
Пусть нам пришел запрос на отрезок [L;R]. Первый вопрос, который приходит в голову: отрезками какой длины нужно перекрывать текущий? Нам необходимо вычислить такое, число, что оно является максимальной степенью двойки и при этом не превосходит длину отрезка-запроса. Чтобы не тратить лишнее время на вычисление этой величины, предподсчитаем эти значения до ответов на запросы.
Сделаем массив pows[MAX_LEN], где MAX_LEN – максимальная длина возможного отрезка-запроса.
pows[i] – такое число, что 
2^pows[i] <= i < 2^(pows[i] + 1).
То есть для каждого числа (фактически для любой возможной длины отрезка-запроса) посчитаем максимальную степень двойки, что 2 в этой степени не больше текущего числа.
Подсчет массива pows:
 


У нас есть необходимая длина, ее степень, подсчитанное значение функций на массиве для всех подотрезков всех степеней. Далее все относительно понятно: возьмем посчитанное значение с подотрезка определенной длины, который начинается в L(левой границе отрезка-запроса), значение с подотрезка определенной длины, который заканчивается в R(правой границе отрезка-запроса) и возьмем от них F(). Это и будет ответ. Так как, мы используем ST только для идемпотентных операций, то двойные перекрытия некоторых фрагментов нам не страшны.





*Об идемпотентных операциях:
Идемпотентность — свойство объекта или операции при повторном применении операции к объекту давать тот же результат, что и при одинарном. 
Формально, функция F является идемпотентной, если выполняется F(x;x) = x;
Min(5, 5) = 5 ? min – идемпотентная функция
Sum(5; 5) = 10 ? сумма не идемпотентная функция
Часто используемые в задачах идемпотентные операции: min, max, gcd (НОД).
 

Task
Time limit: 150 ms,
Memory limit: 256 Mb

Недавно вышла новая игра Counter-Strike 2. В 5и классе учится N человек, и все они хотят поиграть в эту игру. На уроке физ-ры их всех построили в шеренгу. У Физрука Олега Евгеньевича сегодня смешанное настроение: он решил разрешить ученикам поиграть в CS2 вместо физических занятий, но играть они будут только по определенным правилам. А именно: Олег Евгеньевич будет разрешать играть всем ученикам, номер в шеренге которых лежит в отрезке [L;R].  Олег Евгеньевич узнал, что родители детей разрешают играть им в компьютер только ti минут. Но ученики очень любят компьютерные игры, поэтому каждый будет играть ровно ti минут, при этом играть никто не отказывается. Игра происходит следующим образом: выбирается время матча такое, что каждый ученик должен сыграть строго целое число матчей, при этом количество сыгранных матчей у каждого ученика может различаться и такое время матча должно быть максимально возможным. (Например, играют 2 игрока. Если у  играющего 1 время t1 = 12, а у играющего 2 время t2 = 8, то максимально возможное время матча – 4 минуты. 1 играющий сможет сыграть 3 матча по 4 минуты, а 2 – 2 матча по 4 минуты).   Олег Евгеньевич в последнее время усердно занимается математикой, поэтому он решил M раз посчитать максимальное время Q для играющих от L до R. Вам следует проверить Олега Евгеньевича. Для этого следует вывести YES, если он прав, иначе – NO.

Входные данные:
Первая строка входного файла INPUT.TXT содержит число N (1 ≤ N ≤ 10000) – количество ребят. Во второй строке записаны N чисел – ti (1 ≤  ti ≤ 1000), время, которое дают родители iому ребенку на игру. В третьей строке записано число M (1 ≤ M ≤ 108),  количество запросов. Далее, в M строках идут 3 числа, L, R, Q(время, которое посчитал Олег Евгеньевич).

Выходные данные:
В выходной файл OUTPUT.TXT выведите для каждого запроса YES, если Олег Евгеньевич правильно посчитал, иначе – NO.

Пример:
 
INPUT.TXT
 
OUTPUT.TXT
1 3
8 5 6
4
1 2 2
1 3 1
2 3 1
1 3 2
NO
YES
YES
NO
 

(c)  Шалдин В., 2016

Auto CHOOSE THE PROGRAMMING NECESSARY LANGUAGE!
Attach the program source file:
or enter the source code in the language:

Rules for designing programs and a list of errors during automatic task verification
           

Results: