1. 线段数是二叉树 .线段数是递归定义的。则知道线段数的所有操作都是递归的
2. 在定义的时候定义的是节点。而一棵树是由 struct Node{
很多的节点连接起来的 int min, max, sum,left,right; Node *left_child, *right_child; }
3. 综上可知。线段数可以采用动态和静态2种链表的方法
4. 线段数也可以使用数组模拟 int left[], right[] ,left_child[] ,right_child[] ;
5. 类似于堆存储 除了最底层外是满二叉树。则节点 i 的做孩子在 2*i 有孩子在2*i+1(缺点是可能很浪费空间)
定义代码如下(c++) 查询代码如下(c++) 分割符号 | f分隔的 doc上看就好了。
Void Build( Node * cur ,int l, int r) { | void Query(Node *cur, int l ,int r) {
cur->left=l; cur->right=r; | Node *Lc=cur->left_child, *Rc=cur->right_child;
If(l!=r) { | if((l<=cur->left)&&(cur->right<=r)) //覆盖了
cur->left_child=new Node; | printf("%d%d",cur->left,cur->right);
cur->right_child=new Node; | esle {
Build(cur->left_child,l,(l+r)/2); | if(l<=(cur->left+cur->right)/2) Query(Lc,l,r);
Build(cur->right_child,(l+r)/2+1,r); | if(r>(cur->left+cur->right)/2) Query(Rc,l,r);
} else cur->left_child=cur->right_child=Null; | }
} | }
查询 过程其实仅仅是提供一个将查询区间分解的过程
1.当前节点表示的区间包含于查询区间 则该区间就是要分解的区间
2.否则 递归 查询 左 右孩子
(By the way:解释下节点的 min ,max , sum ) start
定义目前工作的数组是 int work[i]; a<=i<=b; node[k];代表第k个节点
Node[k].min = min( work[i] ) a<=i<=b; min 和 max是在插入的时候更新的所以 用的时候直接取就是
Sum 就是∑work(i) end
线段数的 修改 Update
void Insert ( Node *cur, int i ,int v) { //将i位置的值修改为V
Node *Lc =cur ->left_child, *Rc =cur->right_child ;
if(cur->left == i && cur->right ==i) // 改成( cur->left==cur->right ) 可以减少一次运算
cur->min=cur->max=v;
else {
If( i<=(cur->left+cur->right)/2) Insert (Lc , i , v) ;
If( i> (cur->left+cur->right) /2 ) Insert (Rc, i , v );
Cur.sum = Lc->sum+ Rc->sum;
Cur.min = Lc->min<?Rc->min ;
Cur.max = Lc->max>?Rc->max ;
}
}
线段数的 查询(查询 sum) (区间 a-b)之间 有返回值 不是 void
int Qsum( Node * cur ,int l, int r) {
Node *Lc = cur->left_child , *Rc =cur ->right_child; int temp(0) ;
If ( ( l<= cur->left )&&( r>= cur->right))temp+=cur.sum;
Else {
If( l<= (cur->left +cur->right)/2) temp+=Qsum(Lc , l ,r);
If( r> (cur->left + cur->right)/2) temp+=Qsum(Rc, l, r);
Return temp;
}
最后只想说一句。那些所谓的节点所代表的区间就是你工作数组的下标。