多语言展示
当前在线:993今日阅读:39今日分享:10

c++线段树算法

线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。   对于线段树中的每一个非叶子节点[a,b],它的左儿子表示的区间为[a,(a+b)/2],右儿子表示的区间为[(a+b)/2+1,b]。因此线段树是平衡二叉树,最后的子节点数目为N,即整个线段区间的长度。   使用线段树可以快速的查找某一个节点在若干条线段中出现的次数,时间复杂度为O(logN)。而未优化的空间复杂度为2N,因此有时需要离散化让空间压缩。   线段树至少支持下列操作:   Insert(t,x):将包含在区间 int 的元素 x 插入到树t中;   Delete(t,x):从线段树 t 中删除元素 x;   Search(t,x):返回一个指向树 t 中元素 x 的指针。
工具/原料
1

电脑

2

c++

方法/步骤
1

构造线段树,下面给出代码: •void build(int node, int l, int r)  {      if (l == r)          segTree[node] = array[l];   /* 若只有一个元素,节点记录该单元素 */     else{               /* 递归构造左右子树 */            build(2*node, l, (l+r)/2);                     build(2*node+1, (l+r)/2+1, r);   /* 回溯时得到当前node节点的线段信息并进行要求操作 如下为求区间最小值*/  if (segTree[2 * node] <= segTree[2 * node + 1])            segTree[node] = segTree[2 * node];         else            segTree[node] = segTree[2 * node + 1];      }  }

2

区间查询:   int query (int node, int l, int r, int left, int right) {    int p1, p2;/*判断查询区间(light--right)是否包含于被查询区间(l—r)*/   if (left > r || right < l)             return -1;       /*如果当前间隔包含在区间内* /  / *查询间隔返回SegTree [node]*/   if (l >= left && r <= right)             return segTree[node];       /*计算子区间内的最小值*/    p1 = query(2 * node, l, (l + r) / 2, left, right);    p2 = query(2 * node + 1, (l + r) / 2 + 1, r, left, right);       if (p1 == -1)return p2;  if (p2 == -1) return p1;      if (p1 <= p2) return  p1;   return  p2;      }

3

删除节点 void Del(int v,int L,int R) {     if(L>Tree[v].b||R=Tree[v].b){Tree[v].c-- ;return;}    //完全包含   Del(2*v, L,R); //遍历左子树   Del(2*v+1, L,R); //遍历右子树 }

4

单点修改 void Updata(int node, int l, int r, int ind, int add) /*单节点更新*/   {       if( l== r )     {         segTree[node] += add;        return ;      }   int m = ( left + right ) >> 1;   if(ind <= m) Updata(node * 2,left, m, ind, add);   else Updata(node * 2 + 1, m + 1, right, ind, add);   /*回溯更新父节点*/   segTree[node] = min(segTree[node * 2], segTree[node * 2 + 1]);   }

注意事项

注意区间的包含关系

推荐信息