RMQ



前言

RMQ是区间最值查询,多种算法可解,本文采用ST算法、线段树求解
原本使用了莫队算法求解,但还是TLE了,故删除那部分的代码

Balanced Lineup - POJ 3264

题意
询问给定区间中最大值和最小值的差值
思路
ST算法:

	#include <iostream>
	#include <cstdio>
	#include <algorithm>
	#include <cstring>
	#include <cmath>
	#include <stack>
	#include <queue>
	#include <map>
	using namespace std;
	typedef long long ll;
	const int N = 50005;
	const int M = 20;

	int arr_max[N][M];
	int arr_min[N][M];

	void RMQ(int n){
	    for(int j = 1; (1 << j) <= n; j++){
	        for(int i = 1; i + (1 << j) - 1 <= n; i++){
	            arr_max[i][j] = max(arr_max[i][j - 1], arr_max[i + (1 << (j - 1))][j - 1]);
	            arr_min[i][j] = min(arr_min[i][j - 1], arr_min[i + (1 << (j - 1))][j - 1]);
	        }
	    }
	}

	int query(int l, int r, int p){
	    int k = log(r - l + 1)/log(2);
	    if(p == 0)  return max(arr_max[l][k], arr_max[r - (1 << k) + 1][k]);
	    else        return min(arr_min[l][k], arr_min[r - (1 << k) + 1][k]);
	}

	int main(){
	    int n, m;
	    while(~scanf("%d%d", &n, &m)){
	        for(int i = 1; i <= n; i++){
	            scanf("%d", &arr_max[i][0]);
	            arr_min[i][0] = arr_max[i][0];
	        }
	        RMQ(n);

	        while(m--){
	            int p, q;
	            scanf("%d%d", &p, &q);
	            printf("%d\n", query(p, q, 0) - query(p, q, 1));
	        }
	    }
	}


线段树:

	#include <cstdio>
	#include <iostream>
	#include <cstring>
	#include <cstdlib>
	#include <ctime>
	#define lson l, m, rt << 1
	#define rson m + 1, r, rt << 1 | 1
	using namespace std;
	const int N = 200000 + 15;
	const int inf = 0x3f3f3f3f;

	int sum[N << 2][2];
	int a[N];

	void pushUp(int rt){
	    sum[rt][0] = max(sum[rt << 1][0], sum[rt << 1 | 1][0]);
	    sum[rt][1] = min(sum[rt << 1][1], sum[rt << 1 | 1][1]);
	}

	void build(int l, int r, int rt){
	    if(l == r){
	        sum[rt][0] = sum[rt][1] = a[l];
	        return;
	    }
	    int m = (l + r) >> 1;
	    build(lson);
	    build(rson);
	    pushUp(rt);
	}

	int query(int ql, int qr, int p, int l, int r, int rt){
	    if(ql <= l && r <= qr){
	        return sum[rt][p];
	    }
	    int ans = (p == 0 ? 0 : inf);
	    int m = (l + r) >> 1;
	    if(ql <= m)     ans = query(ql, qr, p, lson);
	    if(m <  qr){
	        if(p == 0)  ans = max(ans, query(ql, qr, p, rson));
	        else        ans = min(ans, query(ql, qr, p, rson));
	    }
	    return ans;
	}

	int main(){
	    int n, q;
	    while(~scanf("%d%d", &n, &q)){
	        for(int i = 1; i <= n; i++){ scanf("%d", &a[i]); }
	        build(1, n, 1);

	        while(q--){
	            int l, r;
	            scanf("%d%d", &l, &r);
	            printf("%d\n", query(l, r, 0, 1, n, 1) - query(l, r, 1, 1, n, 1));
	        }
	    }
	}