集训总结1

倍增

为什么要倍增

倍增可以让我们在 n l o g n nlogn nlogn 的时间复杂度内解决问题,如区间最值(RMQ)问题,最近公共祖先(LCA)等,用处广泛。

RMQ ST表

区间最值问题,又称RMQ是指在任意l,r中找出最大值。

做法

我们首先考虑暴力,对于每一个询问,我们可以枚举l到r的元素,更新答案,时间复杂度为 O ( Q ( r − l + 1 ) ) O(Q(r-l+1)) O(Q(rl+1)) Q为询问个数,l和r为询问区间。

我们考虑优化,我们可以维护一个二维数组 f [ i ] [ j ] f[i][j] f[i][j] 表示从 i i i 开始的 2 j 2^j 2j 个数中的最大值,显然 f [ i ] [ 0 ] = a [ i ] f[i][0]=a[i] f[i][0]=a[i],接下来我们考虑转移,对于每一个 f [ i ] [ j ] f[i][j] f[i][j],我们可以将其分为从 i i i 开始到 2 j − 1 2^{j-1} 2j1 和从 i + 2 j − 1 i+2^{j-1} i+2j1 开始到 2 j 2^j 2j 两部分,所以转移方程为(以最大值为例) f [ i ] [ j ] = m a x ( f [ i ] [ j − 1 ] , f [ i + ( 1 < < ( j − 1 ) ) ] ) [ j − 1 ] f[i][j]=max(f[i][j-1],f[i+(1<<(j-1))])[j-1] f[i][j]=max(f[i][j1],f[i+(1<<(j1))])[j1]

对于每一个查询操作,我们可以先令 k = l o g 2 ( r − l + 1 ) k=log_2(r-l+1) k=log2(rl+1)。则可将这段区间用 k k k 分为两段,则可以得出 m a x { a [ l ] , a [ l + 1 ] , ⋯   , a [ r ] } = m a x ( f [ l ] [ k ] , f [ r − ( 1 < < k ) + 1 ] [ k ] ) max \{ a[l],a[l+1], \cdots ,a[r] \} =max(f[l][k],f[r-(1<<k)+1][k]) max{a[l],a[l+1],,a[r]}=max(f[l][k],f[r(1<<k)+1][k])

时间复杂度:预处理 O ( n l o g n ) O(nlogn) O(nlogn),单次询问 O ( 1 ) O(1) O(1)

LCA

对于最近公共祖先,我们可以先假设两个点分别为 x , y x,y x,y,我们在维护一个二维数组 f [ i ] [ j ] f[i][j] f[i][j] 表示 i i i 节点的向上的第 2 j 2^j 2j 个节点是什么,显然 f [ i ] [ 0 ] f[i][0] f[i][0] 表示 i i i 的父节点,状态转移方程为 f [ i ] [ j ] = f [ f [ i ] [ j − 1 ] ] [ j − 1 ] f[i][j]=f[f[i][j-1]][j-1] f[i][j]=f[f[i][j1]][j1] i i i 个向上 2 j − 1 2^{j-1} 2j1 的节点的向上 2 j − 1 2^{j-1} 2j1 个节点。

我们先假设 x x x y y y 在同一深度,考虑从大到小枚举(假设当前枚举到 k k k),则当 f [ x ] [ k ] = f [ y ] [ k ] f[x][k]=f[y][k] f[x][k]=f[y][k] 时表示我们跳过了(即跳到了lca(x,y)或lca(x,y)的父节点),什么都不做,当 f [ x ] [ k ] ≠ f [ y ] [ k ] f[x][k] \neq f[y][k] f[x][k]=f[y][k] 时,令 x = f [ x ] [ k ] , y = f [ y ] [ k ] x=f[x][k],y=f[y][k] x=f[x][k],y=f[y][k] (即跳到 x x x y y y 的第 2 k 2^k 2k 个节点上),当循环结束时,lca(x,y)必然是 x x x y y y 的父节点,返回 f [ x ] [ 0 ] f[x][0] f[x][0] f [ y ] [ 0 ] f[y][0] f[y][0] 即可。

考虑如果 x x x y y y 不在同一深度时怎么做,我们假设 d e p [ x ] > d e p [ y ] dep[x]>dep[y] dep[x]>dep[y] (如果 d e p [ x ] < d e p [ y ] dep[x]<dep[y] dep[x]<dep[y] 则交换 x   y x \, y xy),我们可以从大到小枚举(假设当前枚举到 k k k),若 d e p [ f [ x ] [ k ] ] ≤ d e p [ y ] dep[f[x][k]] \leq dep[y] dep[f[x][k]]dep[y],则令 x = f [ x ] [ k ] x=f[x][k] x=f[x][k],则当循环结束时 x x x y y y 的深度就相同了。

时间复杂度:预处理 O ( n l o g n ) O(nlogn) O(nlogn),单次查询 O ( l o g n ) O(logn) O(logn)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值