poj 3264 Balanced Lineup

福建农林大学 FAFU poj也有一题和这题差不多的,可以去尝试看看

http://acm.fafu.edu.cn/problem.php?id=1272

RMQ poj 3264 Balanced Lineup
//poj 3264 Balanced Lineup

//RMQ

//用RMQ求出最大值和最小值相减即可,具体看一下代码

//学RMQ可以看着个博客http://blog.csdn.net/ice2013/article/details/7545143

//写的挺不错的



//预处理,

//动归求出dp_max[i][j]和dp_min[i][j],dp表示从i开始的2^j个数中的最值,

//2^j一定是偶数,所以把它分为 [i,i+2^(j-1)-1]和[i+2^(j-1), i+2^j -1]这两个区间,

//则dp[i][j]即从这两个区间得出,即dp[i][j] = max(dp[i][1<<(j-1)], dp[i+(1<<(j-1)][j-1])

//询问[a,b]时先求出tmp = log(b-a+1)/log(2.0)

//然后求max(dp[a][tmp], dp[b-(1<<tmp) + 1][tmp])



//注意:动归过程中要注意i+(1<<j)-1 <= n,询问时记得

//dp[b - (1<<tmp) + 1][tmp]前面那个要加 1

#include <stdio.h>

#include <string.h>

#include <math.h>

#include <algorithm>



using namespace std;



#define comein freopen("in.txt", "r", stdin);

#define N 50005

#define INF 1<<30

#define eps 1e-5



int dp_max[N][20], dp_min[N][20];





void init(int n_cow)

{                   //n_cow可以表示成2 的几次方,换底公式

    int index = log(n_cow * 1.0) / log(2.0);

    for(int j = 1; j <= index; ++j)

    {       //i ~ i+(1<<j)-1 之间有 i+(1<<j)-1 - i + 1 即 1<<j个数,包括i

        for(int i = 1; i + (1<<j) - 1 <= n_cow; ++i)

        {   //dp[i][j]表示从i起 2^j个数,i ~ i+(2^j)-1 这个区间的最值

            //如dp[3][2] 表示 3 ~ 6,从3起有2^2个数,因为这样区间长度都为偶数个

            //所以把 区间分为 i~ i+(2^j-1)-1 和 i+(2^j-1)-1 ~ i+(2^j)-1这两个区间

            //长度都为 2^(j-1) 个数, 所以dp[i][j]的记录的最值即为dp[i][j-1] 和

            //dp[i + (2^(j-1))][j-1]这两个部分的最值

            dp_max[i][j] = max(dp_max[i][(j-1)], dp_max[i + (1<<(j-1))][j-1]);

            dp_min[i][j] = min(dp_min[i][(j-1)], dp_min[i + (1<<(j-1))][j-1]);

        }

    }

}



int RMQ(int from, int to)

{   //假如我们需要查询的区间为(i,j),

    //因为这个区间的长度为j - i + 1,所以我们可以取k=log2( j - i + 1),

    //则有:RMQ(A, i, j)=max{F[i , k], F[ j - 2 ^ k + 1, k]}。

    int index = log((to - from + 1) * 1.0) / log(2.0);

    int mx = max(dp_max[from][index], dp_max[to - (1<<index) + 1 ][index]);

    int mn = min(dp_min[from][index], dp_min[to - (1<<index) + 1 ][index]);

    return mx - mn;

}



int main()

{

    int n_cow, n_query;

    while(scanf("%d%d", &n_cow, &n_query) != EOF)

    {

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

        {

            int heigh;

            scanf("%d", &heigh);

            //从第i个起的 2^0 个数中的最大值和最小值

            dp_max[i][0] = dp_min[i][0] = heigh;

        }

        init(n_cow);

        while(n_query--)

        {

            int from, to;

            scanf("%d%d", &from, &to);

            if(from > to)

            {

                from ^= to;

                to ^= from;

                from ^= to;

            }

            printf("%d\n", RMQ(from, to));

        }

    }

    return 0;

}

 

 

你可能感兴趣的:(poj)