1.模板(以维护最小值为例)
#include<iostream> #include<stdio.h> #define LEN 11 #define MAX 1<<30 using namespace std; int arr[LEN]={1,3,7,6,8,5,3,2,7,2,9}; int st[LEN*3]; //segment tree int n; void init(int len){ n=1; while(n<len) n*=2; //不断乘以2,知道>=len for(int i=0;i<n;i++) st[i]=MAX; } void update(int p,int v){ //我们有n(len的二次幂扩增)个叶子作为线段元素 p+=n-1; //地址重定向,变为叶子节点所在地址 st[p]=v; while(p>0){ p=(p-1)/2; //向上跳转到父节点 st[p]=min(st[p*2+1],st[p*2+2]); //更新父节点 } } // 查询[a,b)的最小值,当前函数的查询是[l,r) 。当前根节点为p int query(int a,int b,int p,int l,int r){//外部调用: query(a,b,0,0,n) //如果[a,b)与[l,r)不相交 if(a>=r || b<=l) return MAX; //如果[a,b)包裹住了[l,r) if(a<=l && b>=r) return st[p]; //其他情况,二分进行查询 int v1=query(a,b,p*2+1,l,(l+r)/2); int v2=query(a,b,p*2+2,(l+r)/2,r); return min(v1,v2); } int main(){ init(LEN); int i,a,b; for(i=0;i<LEN;i++) update(i,arr[i]); while(1){ scanf("%d%d",&a,&b); printf("%d\n",query(a,b,0,0,n)); } return 0; }
2.POJ Crane