求给定区间中的最值问题。对于长度为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;
}