RMQ的ST算法

原网址:http://blog.sina.com.cn/s/blog_6e63f59e0101598a.html

关于RMQ的ST算法,以前也大略上看过,也写过程序,可是后来时间长了就忘记了,今天再看到,觉得并没有以前觉得的那么难理解。唉。毕竟以前弱。虽然现在也蒟蒻。
ST算法的原理就是,nlogn预处理出Min[][]和Max[][],查询的时候O(1)查询。
Max[j][i]或Min[j][i]代表,从j的位置开始,长度为2^i的子段中的最大值或最小值。
然后预处理的时候递推。
询问的时候先算出[l,r]的长度的2的对数,然后取出答案即可。
下面贴代码,程序中Min[][],Max[][]存的是最小值最大值的位置,如果这个区间有两个最小值,则保留靠左的那个。查询的时候,若q为0代表查询最小值,q为1代表查询最大值。


#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
using namespace std;
#define mx 100010
int Min[mx][20],Max[mx][20],n,m,a[mx];

void makermq(){
   for (int i = 1;i <= n;i ++) Min[i][0] = Max[i][0] = i;
   
   for (int i = 1;(1 << i) <= n;i ++){
       for(int j = 1;j + (1 << i) - 1 <= n;j ++){
           int p = Min[j][i - 1],q = Min[j + (1 << i - 1)][i - 1];
           if (a[p] < a[q] || (a[p] == a[q] && p < q)) Min[j][i] = p;
           else Min[j][i] = q;
           p = Max[j][i - 1],q = Max[j + (1 << i - 1)][i - 1];
           if (a[p] > a[q] || (a[p] == a[q] && p < q)) Max[j][i] = p;
           else Max[j][i] = q;
       }
   }
}

int ask(int l,int r,int q){
   int tmp = int(log(r - l + 1) / log(2));
   int k1,k2;
   
   if (q == 0){
       k1 = Min[l][tmp],k2 = Min[r - (1 << tmp) + 1][tmp];
       if (a[k1] < a[k2] || (a[k1] == a[k2] && k1 < k2)) return k1;
       else return k2;
   }
   else{
       k1 = Max[l][tmp],k2 = Max[r - (1 << tmp) + 1][tmp];
       if (a[k1] > a[k2] || (a[k1] == a[k2] && k1 < k2)) return k1;
       else return k2;
   }
}

int main(){   
   cin >> n >> m;
   for (int i = 1;i <= n;i ++) cin >> a[i];
   
   makermq();
   
   int l,r,q;
   for (int i = 1;i <= m;i ++){
       cin >> l >> r >> q;
       cout << ask(l,r,q) << endl;
   }
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值