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;
}

 

 

posted @ 2012-07-24 15:39  gabo  阅读(252)  评论(0编辑  收藏  举报