RMQ学习笔记

来源:互联网 发布:安卓ocr软件 编辑:程序博客网 时间:2024/06/08 03:33
问题:
给定一个序列w,给出若干查询,输出区间[l,r]中的最大值或最小值。

原理:
RMQ主要以dp为基础实现的。首先预处理,用f[i][j]表示从i后2^j长度的序列的最大值(或最小值),则f[i][2^0]=w[i],类似线段树,将区间[i,j]分成两等份(由于j,表示的是2^j的区间长度,所以f[i][j]所表示的区间个数一定为偶数),那么状态转移方程为:f[i][j]=max(f[i][j-1],f[i+2^(j-1)][j-1])//2^(j-1)表示分成两份后一份的长度.
对于查询,这里也把区间分成两份。令k=log2(r-l+1),则答案就为ans=max(f[l][k],f[r-2^k+1][k])。
时间复杂度:预处理O(nlogn),查询O(1)。

代码:
for(int j=1; j<=m; ++j)  for(int i=1; i<=m; ++i)    if(i+(1<<j)-1<=m)      f[i][j]=min(f[i][j-1],f[i+(1<<(j-1))][j-1]);    for(int i=1; i<=n; ++i){scanf("%d%d",&x,&y);int k=log(y-x+1)/log(2);printf("%d ",min(f[x][k],f[y-(1<<k)+1][k]));}