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
*/
posted on 2011-10-20 19:10  geeker  阅读(506)  评论(0编辑  收藏  举报