RMQ的两种实现方法

    • 引言
    • 线段树实现RMQ
      • 主要思路
      • 代码实现
      • 时间复杂度
    • ST表实现RMQ
      • 主要思路
      • 代码实现
      • 时间复杂度

引言

RMQ算法(Range Minimum/Maximum Query) 是求区间极值的高效算法,依据所需实现的不同性能可以有多种写法,这里主要讲基于线段树和稀疏表(Sparse Table)的两种方法

线段树实现RMQ

主要思路

线段树是维护区间的一类高效数据结构,依据这个特性,我们可以用线段树实现RMQ算法,用线段树实现的RMQ算法不仅可以查询区间最小值,还可以更改某个节点的值

代码实现

#include
using namespace std;
typedef long long int LL;
const int MAXN=18;
const int INF=1e9;
int num[2*(1<int n;
void init(int base){
    n=1;
    while(n1;
    }
    for(int i=0;i<2*n-1;i++){
        num[i]=INF;
    }
}
void change_k(int k,int a){//将节点k的值赋为a 
    k+=n-1;
    num[k]=a;
    while(k){
        k=(k-1)>>1;
        num[k]=min(num[2*k+1],num[2*k+2]);
    }
}
int get_min(int a,int b,int k,int l,int r){
    if(a<=l&&b>=r) return num[k];
    else if(a>=r||b<=l) return INF;
    else {
//      cout<
        // 递归至左右子树求解 
        int lc=get_min(a,b,2*k+1,l,(l+r)/2);
        int rc=get_min(a,b,2*k+2,(l+r)/2,r);
        return min(lc,rc);
    }
}
int main(){
    scanf("%d",&n);
    int cnt=n;
    init(n);
    for(int i=0;iint tmp;
        scanf("%d",&tmp);
        change_k(i,tmp);
    }
    int a,b;
    scanf("%d %d",&a,&b);
    /*
    int k,num;
    scanf("%d %d",&k,&num);
    change_k(k,num);
    这里还可以实现更改 
    */
    printf("%d\n",get_min(a,b,0,0,n)==INF?-1:get_min(a,b,0,0,n));
}

时间复杂度

预处理时,操作的节点个数为n+n/2+n/4+……,约为2n个,所以复杂度为O(n),每一次查询与修改区间值的复杂度是O(log n).

ST表实现RMQ

主要思路

线段树的查询复杂度为O(log n),对于有多组询问的题还是太慢,有了线段树实现的铺垫,我们思考,是否有一种方法能预先处理出区间极值呢,答案是有的,就是ST表

代码实现

#include
using namespace std;
const int MAXN=18;
int dp[(1<int a[(1<int n;
void st_init(){
    for(int i=0;i0]=a[i];
    }
    for(int j=1;(1<for(int i=0;i+(1<1],dp[i+(1<<(j-1))][j-1]);
        }
    }
}
int get_min(int l,int r){
    int k=(int)(log((double)r-l+1)/log(2.0));
    return min(dp[l][k],dp[r-(1<1][k]);
}
int main(){
    scanf("%d",&n); 
    for(int i=0;iscanf("%d",&a[i]);
    }
    st_init();
    int l,r;
    scanf("%d %d",&l,&r);
    printf("%d\n",get_min(l,r));
}

时间复杂度

显而易见,预处理时的复杂度是O(n log n)的,而查询的复杂度为O(1),可以高效解决多组询问的题目,但基于ST表的写法无法对区间的值进行高效更新.

你可能感兴趣的:(算法心得)