POJ-3264 Balanced Lineup RMQ算法

参考资料:https://blog.csdn.net/niushuai666/article/details/6624672

题意:

给定n头牛和q个区间,以及每头牛的身高,求每个给定区间内最高的牛和最矮的牛高度的差值。

RMQ算法:

RMQ(Range Minimum/Maximum Query),也就是区间最值查询。

RMQ的主要思想:

1.预处理,利用动态规划,理解状态转移方程。

dp[i][j]代表的是从第i个数开始,连续的2^j个数中的最大(小)值。

显然,如果j==0,那么这个最大值就是第i个数本身。于是,我们得到初值条件:dp[i][0]=a[i]

接着,我们开始状态转移。我们不妨让它平分成两段。

平分的原理:dp[i][j]代表的是(i,i+2^j)这个整个长度是(i+i+2^j)/2 = i+2^(j-1)

据此,我们可以得到两段(i,i+2^(j-1))和(i+2^(j-1),j)

于是,我们得到状态转移方程:dp[i][j]=max(dp[i][j-1], dp[i + 2^(j-1)][j-1])

核心代码:

void RMQ(int num)
{
    for(int i=1;i<=n;i++)
    {
        dpMAX[i][0]=b[i];
        dpMIN[i][0]=b[i];
    }
	for(int j=1;(1<<j)<=n;j++)
        for(int i=1;i+(1<<j)-1<=n;i++)
        {
            dpMAX[i][j]=max(dpMAX[i][j-1],dpMAX[i+(1<<(j-1))][j-1]);
            dpMIN[i][j]=min(dpMIN[i][j-1],dpMIN[i+(1<<(j-1))][j-1]);
        }
}

2.查询

比如给定区间(i,j)

这个区间的长度为j - i + 1,我们可以取k=lg( j - i + 1)/lg 2,然后查询(i,k)和(k,j)

核心代码:

int rmqMAX(int s,int v)
{
    int k=(int)(log(v-s+1.0)/log(2.0));
    return max(dpMAX[s][k],dpMAX[v-(1<<k)+1][k]);
}

解题思路:

0.输入数据,注意数组利用全局变量处理

1.写RMQ函数和RMQ查询函数,直接套用,查询最大值和最小值

2.将最大值和最小值作差输出即可

关键:

理解RMQ中的位运算的操作。n<<k代表的是 n * 2^k

猜你喜欢

转载自blog.csdn.net/gg9002/article/details/81066942