POJ 3264 RMQ问题之SparseTable算法

题目链接:http://poj.org/problem?id=3264

先说题意,先给出一个一维数组,然后求任意给定的区间内最大值和最小值的差。

典型的RMQ (Range Minimum/Maximum Query)问题,解题思路种类比较多。

此处用的是ST算法:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
using namespace std;
#define MAXN 50050
int num[MAXN];
int f1[MAXN][100],f2[MAXN][100];
void ST(int n){
    int k,m;
    k=(int)(log((double)n)/log(2.0));
    for(int i=0;i<n;i++){//初值赋予
        f1[i][0]=num[i];
        f2[i][0]=num[i];
    }
    for(int j=1;j<=k;j++){
        for(int i=0;i+(1<<j)-1<n;i++){
            m=i+(1<<(j-1));//m的值是上一个区间的尾数+1
            f1[i][j]=max(f1[i][j-1],f1[m][j-1]);//上两个区间的左区间和右区间
            f2[i][j]=min(f2[i][j-1],f2[m][j-1]);
        }
    }
}
void rmq(int A,int B){
    int t1,t2;
    int C=(int)(log((double)(B-A+1))/log(2.0));
    t1=max(f1[A][C],f1[B-(1<<C)+1][C]);
    t2=min(f2[A][C],f2[B-(1<<C)+1][C]);
    printf("%d\n",t1-t2);
}
int main(){
    int N,Q,A,B;
    while(~scanf("%d%d",&N,&Q)){
        memset(f1,0,sizeof(f1));
        memset(f2,0,sizeof(f2));
        for(int i=0;i<N;i++)
            scanf("%d",&num[i]);
        ST(N);//构建ST数组
        while(Q--){
            scanf("%d%d",&A,&B);
            rmq(A-1,B-1);
        }
    }
    return 0;
}

表示今天又被师父提问憋题了,题目跟此题类似,只要求求出某区间内最大值,要求不可以用线段树。

和另一个徒弟废了半天劲YY出了树状数组的做法,不过代码依旧写不出来。与此同时才发现自己对二进制的掌握和二进制数的熟悉真是差到极点,见到32767也没什么反应,为了以后能够做到全面(比如状态压缩),表示只能硬着头皮继续了。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值