• 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;
    }
  • 相关阅读:
    LeetCode:Length of Last Word
    Team Queue(POJ 2259)
    LeetCode:Largest Rectangle in Histogram(update)
    bzoj4821 && luogu3707 SDOI2017相关分析(线段树,数学)
    luogu1438无聊的数列(区间加等差数列,求一个数的和)
    luogu1081 开车旅行2012 D1T3 (倍增,set,O2)
    bzoj4094 && luogu3097 最优挤奶
    luogu3888 GDOI2014拯救莫里斯 (状压dp)
    noip2017D1T3逛公园(拓扑图上dp,记忆化搜索)
    bzoj1065 NOI2008奥运物流 (dp,树上背包,推式子)
  • 原文地址:https://www.cnblogs.com/gabo/p/2606619.html
Copyright © 2020-2023  润新知