51Nod 1174 求区间最大的数 RMQ

51Nod 1174 求区间最大的数 RMQ

题目链接:51Nod 1174
在很多情况下, 我们求区间最大最小值都是用朴素的遍历算法,其复杂度是O(N), 当存在多次区间最大最小查询时,若查询次数为Q, 那么算法负责度就是O(Q*N) 。 当查询次数 Q 很大时,我们就需要对算法进行优化了。常见的优化方法有: 使用树状数组或者线段树,或者是使用专门的RMQ算法。RMQ是一种专门用来求区间最大最小值的DP。 
树状数组和线段树求区间最值,需要 O(N*log(N)) 的时间负杂度进行初始化,然后O(log(N))的时间负杂度进行查询。
RMQ算法求区间最值,需要O(N*log(N))的时间负杂度进行初始化,但是查询只需要O(1) 。
下面是我对RMQ算法的理解:
以求区间最大值为例,MAX[i][j] 表示的是从i 开始 长度为 2^j 的区间的最大值。

  1. 初始化的过程
    MAX[i][j] 表示的是区间 [i, i + (1 << j) - 1] 的最大值,区间长度是1<
    将区间 [i, i + (1 << j) - 1] 分成两个长度都为 1 << (j - 1) 的区间 m = i + (1 << (j - 1)) - 1;
    [i, m]、[m + 1, m +  (1 << (j - 1)) - 1],
    那么, 我们写出状态转移方程
    MAX[i][j]  = max(MAX[i][j - 1], MAX[m + 1][j - 1])
      = max(MAX[i][j - 1], MAX[ i + (1 << (j - 1))][j - 1])

  2. 查询过程

假如查询区间为[L, R]。区间查询长度为 R - L + 1,令k = (int)log2(R - L + 1), 即小于区间长度的最大的2的幂次方。k 满足大小关系2^k <= (R-L+1)<=2^(k+1),那么区间[L, R]的最大值就必在区间[L,L + (1 << k) - 1], 或者区间[R-(1<中。

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
using namespace std;

//#pragma comment(linker, "/STACK:1024000000,1024000000")

#define FIN             freopen("input.txt","r",stdin)
#define FOUT            freopen("output.txt","w",stdout)
#define fst             first
#define snd             second
#define lson            l, mid, rt << 1
#define rson            mid + 1, r, rt << 1 | 1

typedef __int64  LL;
//typedef long long LL;
typedef unsigned int uint;
typedef pair PII;

const int INF = 0x3f3f3f3f;
const double eps = 1e-6;
const int MAXN = 10000 + 5;
const int MAXM = 50000 + 5;
const int MAXBIT = 16;

int N, Q;
int a, b;
struct RMQ {
    int MAX[MAXN][MAXBIT];
    int log2[MAXN];
    int n, k;
    void init(int _n) {
        n = _n;
        log2[0] = -1;
        for (int i = 1; i <= n; i ++) {
            scanf("%d", &MAX[i][0]);
            if (i) log2[i] = i & (i - 1) ? log2[i - 1] : log2[i - 1] + 1;
        }
        for (int j = 1; j <= log2[n]; j ++) {
            for (int i = 1; i + (1 << j) - 1 <= n; i ++) {
                MAX[i][j] = max(MAX[i][j - 1], MAX[i + (1 << (j - 1))][j - 1]);
            }
        }
    }
    int query(const int& L, const int& R) {
        k = log2[R - L + 1];
        return max(MAX[L][k], MAX[R - (1 << k) + 1][k]);
    }
} rmq;
int main() {
#ifndef ONLINE_JUDGE
    FIN;
#endif // ONLINE_JUDGE
    while (~scanf("%d", &N)) {
        rmq.init(N);
        scanf("%d", &Q);
        while (Q --) {
            scanf("%d %d", &a, &b);
            a ++, b ++;
            int res = rmq.query(a, b);
            printf("%d\n", res);
        }
    }
    return 0;
}

你可能感兴趣的:(ACM____数据结构,ACM____动态规划)