线段树

来源:互联网 发布:樱井知香作品番号 编辑:程序博客网 时间:2024/05/17 09:16

最近看了线段树的例子 就是基于线段树的RMQ结构 ,这个RMQ是个毛毛。。google一下才知到他是区间最值查询。

  给定一个区间 求这个区间的最值;

  给定一个位置将这个位置上的数字改为x;

这就是线段树RMQ 要干的事 并且可以以O(log N)的时间来求得;

我们首先来构造这么一棵树,什么样的树呢?就是好大一颗数

这棵树只有叶子节点才存储我们输入的要查找的值:比如说1 2 3 4 5 要从这里面找,这些值都放在叶子节点上,节点的父亲存储的是这些孩子的最值,一直到根节点是整棵树的最值。

首先要说的就是要构建一个多大的数组呢(我们用数组来实现)? 要看题目的规模 如果最大是N的话,我们要构造2*N 个节点 因为还要存放非叶子节点(N-1个)这样一更就是2*N-1个;

void init(int n){int n1=1;while(n1<n){n1*=2;}for(int i=0;i<2*n1-1;i++){dat[i]=INF;}}

上面是用来初始化数组的,n是规模;

void update(int k,int x){k+=n-1;dat[k]=x;while(k>0){k=(k-1)/2;dat[k]=min(dat[2*k+1],dat[2*k+2]);}}

上面用来更新k位置上的数 逐层向上更新节点;

下面就是递归的来实现查找功能了 :

int  find(int x,int y,int t,int l,int r){if(x>r||y<l)//如果不相交就返回一个我关的值{return MinorMax;//一个无关紧要的值; }if(x<=l&&y>=r)//如果包含在区间内 就返回这个区间对应的最值{return dat[t];} else {int v1=find(a,b,2*k+1,l,(l+r)/2);//向他的左孩子递归int v2=find(a,b,2*k+2,(l+r)/2,r);//向右孩子递归return min(v1,v2);}} 

求 [x,y]中的最小值 ,后面的是方便计算传入的;

在外部调用时出入的是find(x,y,0,0,n);

到这就算结束了。再见

感谢自己坚持,感谢纠错....

1 0
原创粉丝点击