-------------------------------------算法简述-----------------------------------------
ST算法O(nlogn)预处理,O(1)的查询指定区间的最值(以最小值为例)
基本上是把待求区间[l,r]分为两段长为len的区间
左边一段为[l,l+len-1],右边一段为[r-len+1,r]
len必须使得两段区间覆盖待求区间
设所求数组为w
那么,所求最小值就是两个区间的最小值间的最小值
即min(min{w[i],l<=i<=l+len-1},min{w[j],r-len+1<=j<=r})
若都在预先处理中先求得两个区间的最小值
则每次查询的复杂度都是O(1)
---
对len做一个限制:只能为2的幂
在预处理中求出所有mi[b][t] : 以b为起点,长为2^t的区间的最小值.
则求解min(min{w[i],l<=i<=l+len-1},min{w[j],r-len+1<=j<=r})
就变成min(mi[l][t],mi[r-2^t+1][r]),其中t可以由此得出,以保证两段区间可以覆盖待求区间:
t=ln(r-l+1)/ln(2)
---
可以看到mi[b][t]=min(mi[b][t-1],mi[b+2^(t-1)-1][t-1])
特别地对于所有mi[i][0],其值都是w[i];
由此自底向上推出所有的mi[b][t]
mi大小为n*logn,预处理时间复杂度为O(nlogn),查询时间复杂度为O(1)
-----------------------------------------------------代码------------------------------------------------------
在POJ上测试, 反应良好~
不知道怎么样把函数指针指向任意类型的<操作符, 只能总是提供一个"小于"函数
查询指定区间的最小值.
----------------------------------以下是模板-------------------------------------
- template < class Type>
- class rmq_st{
- private:
- Type* body;
- int** mi;
- int size;
- int len;
- int dint(double a){
- int buf=a;
- if(buf>a){
- --buf;
- }
- return buf;
- }
- int mlen(int l,int r){
- double buf=log((double)(r-l+1))/log((double)2);
- return dint(buf)
- }
- bool (*less)(Type& t1,Type& t2);
- public:
- //构造函数 : (待求数组,大小,小于函数)
- rmq_st(Type* con,int s,bool (*lessthan)(Type& t1,Type& t2));
- ~rmq_st();//解构
- Type get_body(int p);//返回指定索引的元素
- int query_index(int l,int r);//返回指定区间最小值的元素索引
- Type query(int l,int r);//返回指定区间的最小元素
- };
- template < class Type>
- rmq_st< Type>::rmq_st(Type* con,int s,bool (*lessthan)(Type& t1,Type& t2)){
- less=lessthan;
- body=con;
- size=s;
- len=mlen(0,s-1)+1;
- mi=new int*[size];
- int i,j;
- for(i=0;i< size;++i){
- mi[i]=new int[len];
- }
- int bound;
- int a,b;
- for(i=0;i< size;++i){
- mi[i][0]=i;
- }
- for(i=1;i< len;++i){
- bound=n-(1<< i)+1;
- for(j=0;j< bound;++j){
- a=mi[j][i-1];
- b=mi[j+(1<< (i-1))][i-1];
- mi[j][i]=less(body[a],body[b])?a:b;
- }
- }
- }
- template < class Type>
- rmq_st< Type>::~rmq_st(){
- int i;
- for(i=0;i< size;++i){
- delete[] mi[i];
- }
- delete[] mi;
- }
- template < class Type>
- Type rmq_st< Type>::get_body(int p){
- return body[p];
- }
- template < class Type>
- int rmq_st< Type>::query_index(int l,int r){
- int length=mlen(l,r);
- int a=mi[l][length];
- int b=mi[r-(1<< length)+1][length];
- return less(body[a],body[b])?a:b;
- }
- template < class Type>
- Type rmq_st< Type>::query(int l,int r){
- int length=mlen(l,r);
- int a=mi[l][length];
- int b=mi[r-(1<< length)+1][length];
- return less(body[a],body[b])?body[a]:body[b];
- }
/*----------------Example : POJ 3264 Memory:7708K Time:3230MS-----------------*/
- int cow[50001];
- int n,q;
- bool cmpmin(int& t1,int& t2){
- return t1< t2;
- }
- bool cmpmax(int& t1,int& t2){
- return t1>t2;
- }
- int main()
- {
- // freopen("1.in","r",stdin);
- scanf("%d %d",&n,&q);
- int i;
- for(i=0;i< n;++i){
- scanf("%d",&cow[i]);
- }
- rmq_st< int> minst(cow,n,cmpmin);
- rmq_st< int> maxst(cow,n,cmpmax);
- int a,b;
- for(i=0;i< q;++i){
- scanf("%d %d",&a,&b);
- --a;
- --b;
- printf("%d/n",maxst.query(a,b)-minst.query(a,b));
- }
- return 0;
- }