树状数组求区间最值(RMQ)

网上找的别人的代码,看了n遍,终于懂了些……写一下心得。

转自于:http://www.cnblogs.com/ambition/archive/2011/04/06/bit_rmq.html  转载请注明出处



lowbit函数不变,用num数组存数列的真实值,用数组tree[k]存 k-lowbit(k)+1到k区间的最值,先用num数组建立tree数组,然后修改时修改num数组和tree数组的值即可。

下面代码以最大值为例:

int lowbit(int x){
    return x&(-x);
}

Init函数用来完成tree的初始化操作。

void init(){
    for(int i=1;i<=n;++i){
        tree[i]=num[i];
        for(int j=1;j
假设在进行tree[i]的初始化,i之前的所有值都已经为正确值。lowbit(i)为tree[i]所能控制到的范围,j依次乘以2,如果在i控制的范围,更新最值,否则停止。



用insert函数完成两个数组的值得修改。

void insert(int p,int v){   //p修改位置,v修改的值
    num[p]=v;
    for(int k=p;k<=n;k+=lowbit(k)){
        if(tree[k]

直接修改num数组。如果v比最值大,更新,否则它一定比后面的最值都小,跳出即可。



用query函数完成区间最值得查询。

int query(int a,int b){    //a为左边界,b为右边界
    int ans=num[b];
    while(1){
        ans=max(ans,num[b]);
        if(a==b) break;
        for(b=b-1;b-a>=lowbit(b);b-=lowbit(b)){
            ans=max(ans,tree[b]);
        }
    }
    return ans;
}
方法是从后往前对每一个tree控制的范围进行判断,如果如在进行到第k项时,该数控制的范围是 [k-Lowbit(k)+1,k], 如果k-Lowbit(k)+1在所求的范围内的话则将该区间的最值加入最值的判断,然后转至地k-Lowbit(k),否则的话就只对第k个数进行最值判断,然后转至k-1即可。



你可能感兴趣的:(树状数组)