线段树单点更新和区间查询

这是最基础的一类线段树问题。将区间扩展为2^n的形式。一律采用左闭右开区间。结点序号从0开始。
#include <cstdio>
#include <iostream>
#include <cstring>
#include <climits>
using namespace std;

const int maxn = 1<<17;
const int inf = INT_MAX;
int n;
int dat[2*maxn-1];

void init(int N){
    n = 1;
    while(n < N) n <<= 1; //扩展线段长度到2的整数次幂
    for(int i=0; i<(n<<1)-1; i++) //序号从0开始
        dat[i] = inf;
}

void update(int k, int a){ //单点更新
    k += n-1;
    dat[k] = a;
    while(k > 0){
        k = (k-1)/2;
        dat[k] = min(dat[k*2+1], dat[k*2+2]);
    }
}

int query(int a, int b, int k, int l, int r){ //左闭右开区间
    if(r <= a || b <= l) return inf;
    else if(a <= l && r <= b) return dat[k];
    else{
        int vl = query(a, b, k*2+1, l, (l+r)/2);
        int vr = query(a, b, k*2+2, (l+r)/2, r);
        return min(vl, vr);
    }
}

int main(){
    int N;
    cin>>N;
    init(N);
    int e;
    for(int i=0; i<N; i++){
        cin>>e;
        update(i, e);
    }
    int q;
    cin>>q;
    while(q--){
        int a, b;
        cin>>a>>b; //左闭右开区间
        int res = query(a, b, 0, 0, n); //注意是扩展区间n
        cout<<res<<endl;
    }
    return 0;
}

一律采用左闭右开区间。结点序号从0开始。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值