倍增

][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]);
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值