Задача

2 /2


Олег Евгеньевич и новая Counter-Strike

Теория Нажмите, чтобы прочитать/скрыть


скачать

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 (НОД).
 

Задача

Недавно вышла новая игра Counter-Strike 2. В 5-м классе учится N человек, и все они хотят поиграть в эту игру. На уроке физкультуры всех учеников построили в шеренгу. У физрука Олега Евгеньевича сегодня смешанное настроение: он решил разрешить ученикам поиграть в CS2 вместо физических занятий, но играть они будут только по определенным правилам. 

Олег Евгеньевич будет разрешать играть всем ученикам, номер в шеренге которых лежит в отрезке \([L;R]\). Олег Евгеньевич узнал, что родители детей разрешают играть им в компьютер только ti минут. Но ученики очень любят компьютерные игры, поэтому каждый будет играть ровно ti минут, при этом играть никто не отказывается. 

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

Например, играют 2 игрока. Если у играющего 1 время \(t_1 = 12\), а у играющего 2 время \(t_2 = 8\), то максимально возможное время матча 4 минуты. 1 играющий сможет сыграть 3 матча по 4 минуты, а 2 – 2 матча по 4 минуты. 

Олег Евгеньевич в последнее время усердно занимается математикой, поэтому он решил M раз посчитать максимальное время Q для играющих от L до R. Вам следует проверить Олега Евгеньевича. Для этого следует вывести YES, если он прав, иначе – NO.

Входные данные
Первая строка содержит число N (\(1 <= N <= 10000\)) – количество ребят. Во второй строке записаны N чисел – ti (\(1 <= t_i <= 1000\)), время, которое дают родители i-ому ребенку на игру. В третьей строке записано число M (\(1 <= M <= 10^8\)), количество запросов. Далее, в M строках идут 3 числа L, R, Q (время, которое посчитал Олег Евгеньевич).

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

 

Примеры
Входные данные Выходные данные
1 3
8 5 6
4
1 2 2
1 3 1
2 3 1
1 3 2
NO
YES
YES
NO

time 150 ms
memory 256 Mb
Правила оформления программ и список ошибок при автоматической проверке задач

Статистика успешных решений по компиляторам
 Кол-во
С++ Mingw-w6412
Комментарий учителя