RMQ(dp)

我一开始是不知道有这么个东西,但是由于最近在学习后缀数组,碰到一道题需要用到后缀数组+RMQ解决的所以不得不学习了。

原理:用A[1...n]表示一组数,dp[i][j]表示从A[i]到A[i+2^j-1]这个范围内的最大值或者最小值也就是以A[i]为起点连续2^j个数的最大值或者最小值,由于元素个数为2^j个,所以从中间平均分成两部分,每一部分的元素个数刚好为2^(j-1)个。 整个区间的最大值一定是左右两部分最大值的较大值,满足动态规划的最优原理。

状态转移方程为:dp[i][j]=min(dp[i][j-1],dp[i+2^(j-1)][j-1]);边界条件为:dp[i][0]=a[i]; 这样就可以在O(NlgN)的时间复杂度内预处理dp数组了。

预处理dp数组:

 for(int i=1;i<=n;i++)

   dp[i,0]:=a[i];
 
for(int j=1;(1<<j)<=n;j++)
{
   for(int i=1;i+(1<<j)-1<=n;j++)
     dp[i,j]=max(dp[i,j-1],dp[i+1<<(j-1),j-1]); 
};
然后到了查询的阶段了,由于我们预处理了dp数组,所以我们在查询的时候时间是很快的!!
 
对于询问[L,R],求出最大的x,满足2^x<=R-L+1,即x=ln(R-L+1)/ln(2) ;[L,R]=[L,L+2^x-1] ∪[R+1-2^x,R],两个子区间元素个数都是2^x个,如图
 
ans(L,R)=max(dp[L,x],dp[R+1-2^x,x])
 
 
 

 

posted on 2013-08-10 09:43  后端bug开发工程师  阅读(351)  评论(0编辑  收藏  举报

导航