线段树及空间开4倍
来源:互联网 发布:divide into python 编辑:程序博客网 时间:2024/04/29 23:03
下面我们来讲解线段树:
线段树有许多应用,给出一个序列,可以在任何一个区间内找到最大,和最小值。可以求区间和等等等等。那么应用就不多说了。毕竟能到这里来的我相信都是为了A题,并且了解线段树的吧! 废话不多说了。 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。 对于线段树中的每一个非叶子节点[a,b],它的左儿子表示的区间为[a,(a+b)/2],右儿子表示的区间为[(a+b)/2+1,b]。因此线段树是平衡二叉树,最后的子节点数目为N,即整个线段区间的长度。 使用线段树可以快速的查找某一个节点在若干条线段中出现的次数,时间复杂度为O(logN)。而未优化的空间复杂度为2N,因此有时需要离散化让空间压缩。当然有兴趣的朋友可以去百度一下离散化去压缩空间。
下面我们来建树:
void pushUp(int rt){ Array[rt]=Array[rt<<1]+Array[rt<<1|1];//当最后1排度为2的父节点的两个子节点存储了值后当然就要更新父节点了。 return;}void buildTree(int l,int r,int rt){//rt代表根节点,l代表左边界,r代表右边界 if(l==r){ scanf("%d",&Array[rt]);//Array代表存储节点的数组 return; } int mid=(l+r)>>1; if(l<=mid){ buildTree(l,mid,rt<<1); } if(r>mid){ buildTree(mid+1,r,rt<<1|1);//这个rt<<1代表乘2, |1代表加1,位运算快多了。 } pushUp(rt); return ;}
下面我们就来贴出完整的代码:
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int n,t;int Array[100000<<2];//100000乘4void pushUp(int rt){ Array[rt]=Array[rt<<1]+Array[rt<<1|1]; return;}void buildTree(int l,int r,int rt){ if(l==r){ scanf("%d",&Array[rt]); return; } int mid=(l+r)>>1; if(l<=mid){ buildTree(l,mid,rt<<1); } if(r>mid){ buildTree(mid+1,r,rt<<1|1); } pushUp(rt); return ;}int query(int left,int right,int l,int r,int rt){ if(left<=l&&r<=right){//查找区间内的值是就返回 return Array[rt]; } int mid=(l+r)>>1; int res=0; if(mid>=left){ res+=query(left,right,l,mid,rt<<1); } if(mid<left){ res+=query(left,right,mid+1,r,rt<<1|1); } return res;}int main(){ while(~scanf("%d%d",&n,&t)){ buildTree(1,n,1); char order[10]; while(t--){ scanf("%s",order); int left,right; if(order[0]=='Q'){ scanf("%d%d",&left,&right); printf("%d\n",query(left,right,1,n,1)); } } } return 0;}
下面很多人就要问了,为什么开数组为什么要开N*4的空间,好,我们来看看这张图。
由图可以很生动形象的看出,为什么很多人开2*N会越界了。图中的X是节点的总数。 但是我不想画图又怎么办呢?推公式??OK下面是我的一个朋友推出来的公式!!! 假设N为节点的总数,No代表度为0的节点的总数。N2代表度为2的节点的总数!由此可得: 倍数= N(max)/No -->No也相当于区间的长度。 N(max)可以看做是一个满二叉树(最好的情况)。N(min)可以看做最后一层只有两个子节点的树(最坏的情况)。
_ | N = No + N2 N = 2 * N2 + 1 |_ k代表层数。 把N2消掉后可以得到。No = (N + 1) / 2 N(max)=2^k - 1 N(k-1层以上的节点总数)=2^(k-1) + 1 所以:No = [(2^(k-1)+1)+1]/2 倍数= N(max)/No 化简可以得到 4- 5/(2^(k-2) + 1 ) -->4-5/(2^(k-1)+2)/2 -->4-5/No 即要开的空间倍数就是4-5/No
1 0
- 线段树及空间开4倍
- 线段树 及 空间为什么是 4倍
- 线段树为什么要开4倍空间
- 线段树为什么要开4倍空间
- 线段树开4N空间证明
- 线段树需要开4倍区间大小的数组的原因
- 线段树为什么要开四倍空间
- 二倍空间的线段树
- 线段树分配空间大小问题
- hdu 6183 线段树的空间优化
- 网上销售还有100倍的空间
- 线段树 模板 及 解释
- 线段树及Lazy-Tag
- 线段树小解及模板
- 线段树讲解及例题
- 线段树模板及习题
- 线段树降空间复杂度,从O(4n)降到O(2n)
- hdu2871 线段树之空间动态存储模拟
- Java数组和链表两种结构的操作效率,在哪些情况下,哪些操作的效率高
- bzoj 1927: [Sdoi2010]星际竞速 费用流
- Machine Learning第一阶段小结
- Spring beanFactory简介
- 50个Java多线程面试题
- 线段树及空间开4倍
- 回调
- hdu 2546 (完全背包)
- hibernate关联映射
- HDU 1513 LCS+滚动数组
- Android——4.2.2 源码目录结构分析
- 在本科应掌握嵌入式哪些技能(学生角度)
- JavaScript原型链
- Java 内部类