RMQ问题如果用线段树实现的话,可以实现O(nlogN)的预处理,O(logN)的查询,速度还可以。
以求最大值为例,将key定义为区间的最大值。建立树时初始化为负无穷大
把任意点a 看成区间[a,a],先把所有的点插入线段树。然后每次用线段树去查询
代码如下:
#include<iostream>
#include<algorithm>
using namespace std;
const int MIN=-2000000000;
//线段树的节点,包括基本域 :左右边界,左右孩子的指针 信息域:key
struct Node{
int ld,rd;//左右边界
Node *lc,*rc;//左右孩子
int key;//信息域,此例子为RMQ,所以存储的为区间最大值
};
//建立一个从区间a到b的空线段树,key初始化为最小负值
Node* buildtree(int a,int b){
Node *p=new Node;
p->ld=a;
p->rd=b;
p->key=MIN;
if(a==b)return p;
p->lc=buildtree(a,(a+b)/2);
p->rc=buildtree((a+b)/2+1,b);
return p;
}
void insert(Node *T,int pos,int key){
if(T->ld==T->rd){
T->key=key;
return;
}
if(pos<=(T->ld+T->rd)/2)
insert(T->lc,pos,key);
else
insert(T->rc,pos,key);
T->key=max(T->lc->key,T->rc->key);
}
int search(Node *T,int a,int b){
int res=MIN;
if(a<=T->ld&&b>=T->rd)
return T->key;
if(a<=(T->ld+T->rd)/2){
int temp=search(T->lc,a,b);
if(res<temp)res=temp;
}
if(b>(T->ld+T->rd)/2){
int temp=search(T->rc,a,b);
if(res<temp)res=temp;
}
return res;
}
int main(){
int n,val;
cin>>n;
Node* root=buildtree(1,n);
for(int i=1;i<=n;i++){
cin>>val;
insert(root,i,val);
}
int ld,rd;
while(cin>>ld>>rd&&ld!=0){
cout<<search(root,ld,rd)<<endl;
}
return 0;
}
/*
10
1 3 8 2 9 7 5 6 4 0
*/
浙公网安备 33010602011771号