ACM 线段树

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

你可能感兴趣的:(acm)