求給定區間中的最值問題。對於長度爲n的數列A,求數組A中下標在[i,j]裏的最小值。
注: 這裏下標從1開始
輸入:
第一行兩個整數n和q,分別表示數列的長度和詢問的次數。
接下來n行爲n個整數,表示數列A中的元素。
接下來q行中,每行有兩個整數,表示所詢問的區間[I, j]的兩個端點
輸出:
對每一個詢問,給出指定區間中的最小值
樣例輸入:
9 2
5 8 1 3 6 4 9 5 7
2 4
6 9
樣例輸出:
1
4
#include <map>
#include <set>
#include <list>
#include <cmath>
#include <queue>
#include <string>
#include <cstdio>
#include <limits>
#include <vector>
#include <iostream>
using namespace std;
const int inf = 1e9;
const int maxn = 1 << 9;
//存儲線段樹的全局數組
int n, tree[2*maxn-1];
int a[] = {5, 8, 1, 3, 6, 4, 9, 5, 7};
//初始化
void init(int n_){
//爲了簡單起見,把元素的個數擴大到2的冪
n = 1;
while(n < n_) n *= 2;//
//初始化所有值
for(int i = 0; i <= 2*n-1; i++){
tree[i] = inf;
}
}
void build(int node, int l, int r){
if(l == r) tree[node] = a[l];
else{
build(node*2, l, (l+r)/2);
build(node*2+1, (l+r)/2+1, r);
if(tree[node*2] < tree[node*2+1]){
tree[node] = tree[node*2];
}else{
tree[node] = tree[node*2+1];
}
}
}
// 把第k個值(0-indexed)更新爲val
void update(int k, int val){
//葉子節點
k += n;
tree[k] = val;
//向上更新
while(k > 0){
k = k / 2;
tree[k] = min(tree[k*2], tree[k*2+1]);
}
}
//求[l, r]的最小值
//後面的參數是爲了計算起來方便而傳入的
//node是節點的編號,begin, end表示這個節點對應的是[begin, end]區間
//在外部調用時,用query(1, 0, n-1, l, r )
int query(int node, int begin, int end, int l, int r){
//如果[a, b)和[l, r)不相交, 則返回inf
if(end < l || r < begin) return inf;
// 如果[a, b)完全包含[l, r),則返回當前節點的值
if(l <= begin && r >= end) return tree[node];
else{
//否則返回兩個兒子中值的較小者
int vl = query(node*2, begin, (begin+end)/2, l, r);
int vr = query(node*2+1, (begin+end)/2+1, end, l, r);
return min(vl, vr);
}
}
int main()
{
int _n = 9, q = 2;
init(_n);
build(1, 0, n-1);
//update(2,10);
//update(8,10);
int _min1 = query(1, 0, n-1, 1, 3);
int _min2 = query(1, 0, n-1, 5, 8);
cout << _min1 << endl;
cout << _min2 << endl;
return 0;
}