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 */