倍增

原创 2016年08月30日 21:52:24

][TOC]

例子

快速幂、 斐波那契数列、 RMQ、 树上倍增


RMQ 区间最值查询

*令A[i]存储我们要求最值的数列,F[i][j]表示从第i个位置开始,往后的2^j个数字中,最大的数字是什么
*我们对j从小到大枚举。每次处理.f[i][j]的时候,f[i][0~j−1]都已经处理好了
*因为j最大到logn,所以预处理的复杂度为O(nlogn)


状态转移方程:

f[i][j]=max(f[i][j−1],f[i+2^(j−1)][j−1])

↑ eg. f[5][3]=max(f[5][2],f[9][2]) (f[5][2]是5到9,f[9][2]是9到13)


void init_rmq (int n){
    for(int i=1;i<=n;i++)
        f[i][0]=a[i];
    for(int j=1;(1<<j)<n;++j)
        for(int i=1;i<=n;++i)
            if(i+(1<<j)-1<=n)
                f[i][j]=max(f[i][j-1],
                            f[i+(1<<j-1)][j-1]);
}

int query_rmq(int i,int j){
    int k = log(j-i+1) / log(2);
    return max(f[i][k],f[j-(1<<k)+1][k]);
}

倍增LCA

令father[i][j]记录编号为i的点,往上蹦2^j次的父亲

状态转移方程:

f[i][j]=f[f[i][j-1][j-1]]
注意!!!!!!!!!!数组要开两倍空间!!!!!无向边!!!

初始状态:f[i][0]=a[i-1];
void init_lca (int n){
    for(int j=1;(1<<j)<=n;++j)
        for(int i=1;i<=n;++i)
            if(f[i][j]!=-1)
                f[i][j]=f[f[i][j-1]][j-1];
}

int query_lca(int i,int j){
    int k = log(j-i+1) / log(2);
    return max(f[i][k],f[j-(1<<k)+1][k]);
}
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

【白话系列】倍增算法

【序言】         我认为吧,所有能够优化复杂度的算法都是神奇的,所有能够化繁琐为形象的文字都是伟大的。一直觉得倍增算法是个很神奇的东西,所以决定写点东西纪念一下它。但是作为一个非常不称职的O...

LCA倍增法

LCA在线倍增法实际上是将上升的步数用二进制来表示,经过试跳一个级数来确定是否可以上升,最终找到LCA,整个路径长度假设是n的话,这个过程就是O(logn)的。 代码如下 1. DFS预处...

倍增思想在算法中的应用

  • 2012年10月08日 17:44
  • 330KB
  • 下载

rmq算法(倍增)

  • 2012年12月17日 21:02
  • 1KB
  • 下载

使用倍增算法(Prefix Doubling)构造后缀数组

如果采用对每个后缀排序的方法来生成后缀数组,即使采用快速排序,由于每次比较的对象是字符串(设输入字符串的长度为n),因此每一个比较操作的复杂度不再是常数,而是O(n),快速排序本身的平均情况下时间复杂...

倍增与分治

  • 2016年08月03日 09:06
  • 145KB
  • 下载

【BZOJ2815】【ZJOI2012】灾难 阿米巴和小强题 动态倍增LCA 灾难树

题解: 我们构建一颗灾难树,使得一个节点的任意一个祖先灭绝,则其会灭绝。 则可以按照拓扑序扫每个节点,然后加入到灾难树中时只需要把它的父亲赋成它所有食物的LCA就好了。 我们可以动态处理每个节点...
  • Vmurder
  • Vmurder
  • 2015年03月06日 20:24
  • 1316

minist训练图像倍增器

  • 2015年08月23日 12:45
  • 29.52MB
  • 下载

后缀数组倍增算法实现

  • 2012年09月02日 16:24
  • 2KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:倍增
举报原因:
原因补充:

(最多只允许输入30个字)