一、前言
神仙题目
二、题解
30 p t s 30pts 30pts:
考虑枚举右端点 r r r。
建立一颗答案线段树 A T r e e ATree ATree,线段树的 i i i 号节点表示 min ( a [ j ] − a [ i ] ) ( i ≤ j ≤ r , a [ j ] > a [ i ] ) \min (a[j] - a[i]) (i \leq j \leq r,a[j] > a[i]) min(a[j]−a[i])(i≤j≤r,a[j]>a[i])。
有一个朴素做法,就是枚举所有满足要求的 j j j, 然后更新。(甚至不需要线段树,这里加上线段树是为了拓展到 100 p t s 100pts 100pts 的做法)
时间复杂度: O ( n q ) / O ( n q l o g 2 ( n ) ) \mathcal{O (nq)}/\mathcal{O(nq log_2(n))} O(nq)/O(nqlog2(n))
100 p t s 100pts 100pts:
太辣鸡的朴素做法,怎么优化呢?
我们可以发现,有些一定没有用的 j j j 被我们更新了,考虑怎么跳过这些 j j j。
首先朴素做法的流程我们可以写成:
- p o s ← max k ( k < p o s ) pos \leftarrow \max k (k < pos) pos←maxk(k<pos)
- A T r e e [ p o s ] ← min ( A T r e e [ p o s ] , a [ p o s ] − a [ i ] ) ATree[pos] \leftarrow \min (ATree[pos], a[pos] - a[i]) ATree[pos]←min(ATree[pos],a[pos]−a[i])
- R ← a [ p o s ] R \leftarrow a[pos] R←a[pos]
- 返回操作 1 1 1
然后我们进行一个小小的优化:
- p o s ← max k ( k < p o s , a [ i ] ≤ a [ k ] ≤ R ) pos \leftarrow \max k (k < pos, a[i] \leq a[k] \leq R) pos←maxk(k<pos,a[i]≤a[k]≤R) ( R R R最开始取 ∞ \infty ∞)
- A T r e e [ p o s ] ← min ( A T r e e [ p o s ] , a [ p o s ] − a [ i ] ) ATree[pos] \leftarrow \min (ATree[pos], a[pos] - a[i]) ATree[pos]←min(ATree[pos],a[pos]−a[i])
- R ← a [ p o s ] R \leftarrow a[pos] R←a[pos]
- 返回操作 1 1 1
这个表示我们不考虑 k ≤ p o s , a [ k ] ≥ a [ p o s ] k \leq pos, a[k] \geq a[pos] k≤pos,a[k]≥a[pos] 的点,因为 k k k 又没有 p o s pos pos 优又不可能在 p o s ∈ [ l , r ] pos \in [l, r] pos∈[l,r] 的时候处于 [ l , r ] [l, r] [l,r] 中。
然后我们进行一个大大的优化:
- p o s ← max k ( k < p o s , a [ i ] ≤ a [ k ] ≤ ⌊ R − a [ i ] 2 ⌋ + a [ i ] ) pos \leftarrow \max k (k < pos, a[i] \leq a[k] \leq \lfloor \frac{R - a[i]}{2} \rfloor + a[i]) pos←maxk(k<pos,a[i]≤a[k]≤⌊2R−a[i]⌋+a[i]) ( R R R最开始取 ∞ \infty ∞)
- A T r e e [ p o s ] ← min ( A T r e e [ p o s ] , a [ p o s ] − a [ i ] ) ATree[pos] \leftarrow \min (ATree[pos], a[pos] - a[i]) ATree[pos]←min(ATree[pos],a[pos]−a[i])
- R ← a [ p o s ] R \leftarrow a[pos] R←a[pos]
- 返回操作 1 1 1
考虑 k , i , p o s k, i, pos k,i,pos (纵坐标为下标对应的 a a a, 横坐标为下标)
如果 a [ k ] > ⌊ R − a [ i ] 2 ⌋ + a [ i ] a[k] > \lfloor \frac{R - a[i]}{2} \rfloor + a[i] a[k]>⌊2R−a[i]⌋+a[i],那么我们会选择 ( k , p o s ) (k, pos) (k,pos),那么 A T r e e [ k ] ← min ( A T r e e [ k ] , a [ k ] − a [ i ] ) ATree[k] \leftarrow \min (ATree[k], a[k] - a[i]) ATree[k]←min(ATree[k],a[k]−a[i]) 就不会产生贡献。
然后我们高兴的发现,操作个数不超过 l o g 2 V log_2V log2V(因为每次 [ a [ i ] , R ] [a[i], R] [a[i],R] 这个区间都会至少减半)。
所以时间复杂度是 O ( n ( l o g 2 V ) 2 ) \mathcal{O (n (log_2V) ^2)} O(n(log2V)2)