倍增算法的一些应用

我所了解的倍增算法

我所了解的倍增算法大体是这样的,当我们想知道2^n次方这么个长度范围内的某个值(如最大值或者最小值),如果我知道了所有的2^(n-1)次方长度范围内的值,这样我就可以通过我所知道的这些值中算出我要的值。具体在定义的时候一般是这样的

anc[i][k] 表示以i开头,长度为2^k次方的这么一个区间我们所要的值(这里以最小值为例),那么当我知道一个数组的所有数之后,我就可以用nlogn的时间来进行预处理,然后可以用logn的时间来获得任意一个区间的最小值

 

具体可以这样来做

for (int i=1;i<=n;i++) anc[i][0] = a[i];
for (int k=1;k<=20;k++)
    for (int i=1;i<=n;i++) 
        anc[i][k] = min(ans[i][k-1], ans[i + (1<<(k-1))][k-1]);

因为我们知道任意一个区间都可以有2的多个次方组成,故可以用多个2^k来组成一个区间,这样就可以在logn的时间求出我们想要的值

 

倍增算法的应用

1,在求最大值及最小值上的应用

正如上面所说的,倍增算法可以用来求最小值,同时也可以用来求最大值,只要把min改成max就可以了,这也是所说的RMQ算法

 

2,用来求LCA

LCA就是最近公共祖先,就是一棵树,求两个结点的最近公共祖先,我们也可以像刚才的代码一样预处理出anc数组

for (int i=1;i<=n;i++) anc[i][0] = fa[i];
for (int k=1;k<=20;k++)
    for (int i=1;i<=n;i++) 
        anc[i][k] = min(ans[i][k-1], ans[i + (1<<(k-1))][k-1]);

只是预处理的时候距离为1的祖先应该是其父亲结点,然后在求两个结点的最近公共祖先时,先把深度的结点上升到和深度较小的结点一样的深度,具体的上升方法也用anc这个数组来升,就是把u节点上升到第H个祖先的位置,即长度为H,起始位置为u,然后在应用anc数组,找到两个结点的Lca,具体看下面代码

上升
void swim(int &x,int H){for (int i=0;H>0;i++){if (H&1) x=anc[x][i]; H/=2; }}

获得LCA
int Lca(int u,int v)
{
     int i;
     if (dep[u]>dep[v]) swap(u,v); //printf("%d %d\n",u,v);
     swim(v,dep[v]-dep[u]); //printf("%d\n",v);
     if (u==v) return u;
     for (; ;)
     {
          for (i=0;anc[u][i]!=anc[v][i];i++); //printf("%d %d %d %d\n",u,anc[u][i],v,anc[v][i]);
          if (i==0) return anc[u][0];
          u=anc[u][i-1]; v=anc[v][i-1];
     }
     return -1;
}

 

3,扩展应用

可以看出,只要是满足结合律,我们都可以用这个方法来求,如gcd(最大公约数),没想到吧,一个区间的最大公约数也可以这样来求,其他的只要满足结合律关系的,在对区间询问时,都可以考虑一下这样的算法

 

4,换位思考后的应用

我们一般都是考虑区间里面的某个值,可不可以倒过来,考虑值,然后存区间呢?

曾经碰到过这样一个题:

  X轴上有很多区间,现在有m个询问,给你一个区间[L,R],问这个区间内最多有多少个不重复的区间

这个题就可以考虑倍增算法,anc[i][k]表示以i开始,2^k次方个不想交的区间的最右边的位置的最小值,于是以同样的做法,稍加处理就可以得到任意一个区间的答案

 

以上便是我给出的几个方面的应用,当然1,2都是显然的,而3,4都是要求结合实际问题来讨论的

转载于:https://www.cnblogs.com/chensunrise/p/4859173.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值