0
点赞
收藏
分享

微信扫一扫

面试的考验

得一道人 2022-03-15 阅读 16
算法

一、前言

神仙题目

二、题解

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])(ijr,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

首先朴素做法的流程我们可以写成:

  1. p o s ← max ⁡ k ( k < p o s ) pos \leftarrow \max k (k < pos) posmaxk(k<pos)
  2. 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])
  3. R ← a [ p o s ] R \leftarrow a[pos] Ra[pos]
  4. 返回操作 1 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) posmaxk(k<pos,a[i]a[k]R) ( R R R最开始取 ∞ \infty )
  2. 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])
  3. R ← a [ p o s ] R \leftarrow a[pos] Ra[pos]
  4. 返回操作 1 1 1

这个表示我们不考虑 k ≤ p o s , a [ k ] ≥ a [ p o s ] k \leq pos, a[k] \geq a[pos] kpos,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] 中。

然后我们进行一个大大的优化:

  1. 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]) posmaxk(k<pos,a[i]a[k]2Ra[i]+a[i]) ( R R R最开始取 ∞ \infty )
  2. 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])
  3. R ← a [ p o s ] R \leftarrow a[pos] Ra[pos]
  4. 返回操作 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]>2Ra[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)

举报

相关推荐

0 条评论