快速查询区间最值——RMQ算法(线段树实现代码)

本文介绍了一种通过线段树和动态规划解决区间内最大最小值差问题的方法。利用线段树更新和查询区间最值,同时采用动态规划预处理不同长度区间的最值,以高效解答针对多个查询区间的问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

要求找出区间内的最大最小值的差。

#include<stdio.h>
#include<string.h>
#include<math.h>
#define lson l,m,p<<1
#define rson m+1,r,p<<1|1
#define Max(a,b) (a<b?b:a)
#define Min(a,b) (a<b?a:b)
#define INF 999999999

/*线段树
int N,M;
int MinP[50000*4+10],MaxP[50000*4+10];
int minT,maxT;

void Update(int val,int K,int l,int r,int p){
    int m=(l+r)>>1;
    if(l==r){
        MaxP[p]=MinP[p]=val;
        return;
    }
    if(K<=m)
        Update(val,K,lson);
    else
        Update(val,K,rson);
    MaxP[p]=Max(MaxP[p<<1],MaxP[p<<1|1]);
    MinP[p]=Min(MinP[p<<1],MinP[p<<1|1]);
}

void Query(int L,int R,int l,int r,int p){
    int m=(l+r)>>1;
    if(L<=l&&r<=R){
        minT=Min(minT,MinP[p]);
        maxT=Max(maxT,MaxP[p]);
        return;
    }
    if(L<=m)
        Query(L,R,lson);
    if(R>=m+1)
        Query(L,R,rson);
}

int main(){
    int i,val,a,b;
    scanf("%d %d",&N,&M);
    for(i=1;i<=N;i++){
        scanf("%d",&val);
        Update(val,i,1,N,1);
    }
    for(i=1;i<=M;i++){
        scanf("%d %d",&a,&b);
        minT=INF;
        maxT=0;
        Query(a,b,1,N,1);
        printf("%d\n",maxT-minT);
    }
    return 0;
}


ST(动态规划)*/
int N,M;
int A[50001];
int FMin[50001][20],FMax[50001][20];

void Init(){
    int i,j;
    for(i=1;i<=N;i++)
        FMin[i][0]=FMax[i][0]=A[i];
    for(i=1;(1<<i)<=N;i++){   //按区间长度递增顺序递推 
        for(j=1;j+(1<<i)-1<=N;j++){   //区间起点 
            FMin[j][i]=Min(FMin[j][i-1],FMin[j+(1<<(i-1))][i-1]);
            FMax[j][i]=Max(FMax[j][i-1],FMax[j+(1<<(i-1))][i-1]);
        }
    }   
}

int Query(int l,int r){
    int k=(int)(log(r-l+1)/log(2));
    return Max(FMax[l][k],FMax[r-(1<<k)+1][k])-Min(FMin[l][k],FMin[r-(1<<k)+1][k]);
}

int main(){
    int i,a,b;
    scanf("%d %d",&N,&M);
    for(i=1;i<=N;i++)
        scanf("%d",&A[i]);
    Init();
    for(i=1;i<=M;i++){
        scanf("%d %d",&a,&b);
        printf("%d\n",Query(a,b));
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值