Используйте дерево сегментов - рекурсивное разбиение диапазона на меньшие диапазоны. Каждый интервал [ a , b ] ваших операций обновления может быть разбит на O ( log n ) диапазонов в этом рекурсивном разделе. Для каждого диапазона [ x , y ] store:[ 1 , n ][ а , б ]O ( журналн )[ х , у]
- Число интервалов [ a , b ] , которые были увеличены и не уменьшены, так что [ x , y ] является одним из диапазонов, на которые разбивается [ a , b ]с ( х , у)[ а , б ][ х , у][ а , б ]
- Число ячеек, которые не покрыты разделенными подмножествами интервалов, которые в [ x , y ] или ниже в рекурсиии ( х , у)[ х , у]
Тогда, если рекурсивно разбито на [ x , z ] и [ z + 1 , w ], мы имеем
u ( x , y ) = { 0, если c ( x , y ) > 0 u ( x , z ) + u ( z + 1 , y ) в противном случае[ х , у][ Х , г][ z+ 1 , ш ]
и ( х , у) = { 0у ( х , г) + u ( z+ 1 , у)если с ( х , у) > 0в противном случае
поэтому мы можем обновлять каждое значение
в постоянное время, когда изменяются другие данные для диапазона. На каждый запрос поддержки можно ответить, посмотрев на
u ( 1 , n ) .
и ( х , у)ты ( 1 , н )
Чтобы выполнить операцию увеличения , разбейте [ a , b ] на диапазоны O ( log n ) , увеличьте c ( x , y ) для каждого из этих диапазонов и используйте приведенную выше формулу для пересчета u ( x , y) ) для каждого из этих диапазонов и каждого из их предков. Операция уменьшения аналогична уменьшению вместо увеличения.( а , б )[ а , б ]O ( журналн )с ( х , у)и ( х , у)