今天是六一儿童节,先祝各位六一儿童节快乐
今天想和大家一起学习一下线段树:
1. 创建线段树
对于线段树我们可以选择和普通二叉树一样的链式结构。我们可以用数组来存储,下面的讨论及代码都是数组来存储线段树,节点结构如下(注意到用数组存储时,有效空间为2n-1,实
际空间确不止这么多,比如上面的线段树中叶子节点1、3虽然没有左右子树,但是的确占用了数组空间,实际空间是满二叉树的节点数目。 是树的高度,但是这个空间复杂度也是
O(n) 的 )。
定义包含n个节点的线段树 SegTreeNode segTree[n],segTree[0]表示根节点。那么对于节点segTree[i],它的左孩子是segTree[2*i+1],右孩子是segTree[2*i+2]。
我们可以从根节点开始,平分区间,递归的创建线段树,线段树的创建函数如下:
1 int add(int x,int l,int r) 2 { 3 s[x].l=l;s[x].r=r; 4 int mid=(l+r)/2;//利用二分的思想来做; 5 if(l==r) 6 return s[x].dis=a[l]; 7 s[x].dis=add(x*2,l,mid)+add(x*2+1,mid+1,r);//这只是求和; 8 return s[x].dis; 9 }
2.修改
我么就以一个最常见的例子来说
最经常的是“C,x,y”,把a[x]改成v;
代码:
1 void chag(int p,int x,int v) 2 { 3 if(t[p].l==t[p].r) 4 { 5 t[p].dat+=v; 6 return; 7 } 8 int mid=(t[p].l+t[p].r)/2; 9 if(mid>=x) 10 chag(p*2,x,v); 11 else 12 chag(p*2+1,x,v); 13 t[p].dat=t[2*p].dat+t[2*p+1].dat; 14 }
最后求了,我给出一个求和代码
代码:
1 int asked(int p,int l,int r) 2 { 3 if(l<=t[p].l&&r>=t[p].r) 4 return t[p].dat; 5 int mid=(t[p].l+t[p].r)/2; 6 int maxx=0; 7 if(l<=mid) 8 maxx+=asked(p*2,l,r); 9 if(r>mid) 10 maxx+=asked(p*2+1,l,r); 11 return maxx; 12 }
today is over