倍增数组基础

应用:

      给定一个数列a,

      基本的倍增数组可以用O(1)的时间复杂度计算出区间[i,j]的最值

具体操作:

    维护倍增数组

     1、状态 dp[j][i]表示区间从i到 i+(2^j)-1,即以i开始长度为2^j 这个区间范围的最值。(下面以最小值为例)

     2、状态转移方程:dp[j][i]=min{dp[j-1][i],dp[j-1][i+(1<<(j-1))]};  

         

    3、边界值:dp[0][i]=a[i]    //以i开始长度为2^0=1

   求数组a在区间【i,j】间的最值。

   首先计算一个最大的k,使得2^k<=区间长度(j-i+1).

   k=log(j-i+1)/log2

  则可求得 答案  min(dp[k][i],dp[k][j-(2^k)+1]).

 

基础题:https://www.luogu.com.cn/problem/P2880

#include<bits/stdc++.h>
using namespace std;

const int N=50005;
int n,q,h[N],mi[21][N],ma[21][N],k,maxn,minn,a,b,x; 
int main()
{
    scanf("%d%d",&n,&q);
    for(int i=1; i<=n; i++){
    	scanf("%d",&x);
		mi[0][i]=ma[0][i]=x; 
	}
	for(int j=1; j<=21; j++)
	{
		for(int i=1; i+(1<<j)-1<=n; i++){
			mi[j][i]=min(mi[j-1][i],mi[j-1][i+(1<<(j-1))]);
			ma[j][i]=max(ma[j-1][i],ma[j-1][i+(1<<(j-1))]);
		} 
	} 
	for(int i=1; i<=q; i++){
		 scanf("%d%d",&a,&b);
		 k=(int)(log(b-a+1.0)/log(2.0));
		 maxn=max(ma[k][a],ma[k][b-(1<<k)+1]);
		 minn=min(mi[k][a],mi[k][b-(1<<k)+1]);
		 printf("%d\n",maxn-minn);
	}
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值