势能线段树
线段树能够通过打懒标记实现区间修改的条件有两个:
- 能够快速处理懒标记对区间询问结果的影响
- 能够快速实现懒标记的合并
但有的区间修改不满足上面两个条件(如区间整除/开方/取模等)。
但某些修改存在一些奇妙的性质,使得序列每个元素被修改的次数有一个上限。
所以可以在线段树每个节点上记录一个值,表示对应区间内是否每个元素都达到修改次数上限。区间修改时暴力递归到叶子节点,如果途中遇到一个节点,这个节点的对应区间内每个元素都达到修改次数上限则在这个节点 r e t u r n return return掉。
可以证明复杂度为 O ( ( n + m log n ) × l i m ) O((n+m\log n)\times lim) O((n+mlogn)×lim),其中 n n n为序列长度, m m m为询问次数, l i m lim lim为修改次数上限。
LOJ6029——线段树区间除法
对于每个区间维护区间内的 最大值 M a x Max Max 和 最小值 M i n Min Min,对于整除操作,如果有 M a x − ⌊ M a x d ⌋ = M i n − ⌊ M i n d ⌋ Max-\lfloor\frac{Max}{d}\rfloor = Min − \lfloor\frac{Min}{d}\rfloor Max−⌊dMax⌋=Min−⌊dMin⌋,就转化为区间减。否则直接向下递归。
考虑何时满足 M a x − ⌊ M a x d ⌋ = M i n − ⌊ M i n d ⌋ Max-\lfloor\frac{Max}{d}\rfloor = Min − \lfloor\frac{Min}{d}\rfloor Max−⌊dMax⌋=Min−⌊dMin⌋:
设 M a x = k 1 d + c 1 , M i n = k 2 d + c 2 ( c 1 , c 2 ∈ [ 0 , d − 1 ] , d ≥ 2 ) Max=k_1d+c_1,Min=k_2d+c_2(c_1,c_2\in[0,d-1],d\geq 2) Max=k1d+c1,Min=k2d+c2(c1,c2∈[0,d−1],d≥2)
M a x − ⌊ M a x d ⌋ = M i n − ⌊ M i n d ⌋ Max-\lfloor\frac{Max}{d}\rfloor=Min-\lfloor\frac{Min}{d}\rfloor Max−⌊dMax⌋=Min−⌊dMin⌋
M a x − M i n = ⌊ M a x d ⌋ − ⌊ M i n d ⌋ Max-Min=\lfloor\frac{Max}{d}\rfloor-\lfloor\frac{Min}{d}\rfloor Max−Min=⌊dMax⌋−⌊dMin⌋
( k 1 − k 2 ) d + c 1 − c 2 = k 1 − k 2 (k_1-k_2)d+c_1-c_2=k_1-k_2 (k1−k2)d+c1−c2=k1−k2
( k 1 − k 2 ) ( d − 1 ) = c 2 − c 1 (k_1-k_2)(d-1)=c_2-c_1 (k1−k2)(d−1)=c2−c1
若 k 1 = k 2 , 则 c 2 = c 1 , 所 以 M a x = M i n 若k_1=k_2,则c_2=c_1,所以Max=Min 若k1=k2,则c2