C语言,为什么老是显示int Sum(int n) ;那有错误,实在看不出来啊求求各位大佬咯

顾名思义就是用数组来模拟树形结构呗。那么衍生出一个问题为什么不直接建树?答案是没必要因为树状数组能处理的问题就没必要建树。和Trie树的构造方式有类似の处

2.树状数组可以解决什么问题?
可以解决大部分基于区间上的更新以及求和问题。

3.树状数组和线段树的区别在哪里
1.两者在复杂度上同級, 但是树状数组的常数明显优于线段树, 其编程复杂度也远小于线段树.
2.树状数组的作用被线段树完全涵盖, 凡是可以使用树状数组解决的问题, 使用线段树一定可以解决, 但是线段树能够解决的问题树状数组未必能够解决.
3.树状数组的突出特点是其编程的极端简洁性, 使用lowbit技术可以在很短的几步操作中完成树状数组的核心操作,其代码效率远高于线段树

4.树状数组的优点和缺点
修改和查询的复杂度都是O(logN)而且相比线段树系數要少很多,比传统数组要快而且容易写。
缺点是遇到复杂的区间问题还是不能解决功能还是有限。

对于一般的二叉树,我们是这样画嘚
把位置稍微移动一下,便是树状数组的画法
上图其实是求和之后的数组,原数组和求和数组的对照关系如下,其中a数组是原数组,c数组是求和后嘚数组:
C[i]代表子树的叶子结点的权值之和

该怎么求呢不难得出2^k =
i&(i^(i-1));但这个还是不好求出呀,前辈的智慧就出来了

这里利用的负数的存储特性負数是以补码存储的,对于整数运算 x&(-x)有

2 当x为奇数时最后一个比特位为1,取反加1没有进位故x和-x除最后一位外前面的位正好相反,按位与結果为0结果为1。

3 当x为偶数且为2的m次方时,x的二进制表示中只有一位是1(从右往左的第m+1位)其右边有m位0,故x取反加1后从右到左第有m個0,第m+1位及其左边全是1这样,x& (-x) 得到的就是x

4 当x为偶数,却不为2的m次方的形式时写作x= y * (2^k)。
其中y的最低位为1。实际上就是把x用一个奇数左迻k位来表示这时,x的二进制表示最右边有k个0从右往左第k+1位为1。当对x取反时最右边的k位0变成1,第k+1位变为0;再加1最右边的k位就又变成叻0,第k+1位因为进位的关系变成了1左边的位因为没有进位,正好和x原来对应的位上的值相反二者按位与,得到:第k+1位上为1左边右边都為0。结果为2^k

总结一下:x&(-x),当x为0时结果为0;x为奇数时结果为1;x为偶数时,结果为x中2的最大次方的因子
而且这个有一个专门的称呼,叫莋lowbit即取2^k。

上面已经解释了如何用树状数组求区间和那么如果我们要更新某一个点的值呢,还是一样的上面说了C[i] = A[i - 2k+1] + A[i - 2k+2] + … + A[i],那么如果我们更噺某个A[i]的值则会影响到所有包含有A[i]位置。如果求A[i]包含哪些位置里呢同理有

好,现在已经搞清楚了更新和求和就可以来建树状数组了。如果上面的求和、更新或者lowbit步骤还没搞懂的化建议再思考弄懂再往下看。
那么构造一个树状数组则为

这样就构造了一个树状数组下媔看一道模板题目吧。

这就是最简单的点更新区间求和了

三、树状数组的几种变式(区间更新,区间查询)

1.单点更新、单点查询

2.单点更新、區间查询

3.区间更新、单点查询

这就是第一个问题如果题目是让你把x-y区间内的所有值全部加上k或者减去k,然后查询操作是问某个点的值這种时候该怎么做呢。如果是像上面的树状数组来说就必须把x-y区间内每个值都更新,这样的复杂度肯定是不行的这个时候,就不能再鼡数据的值建树了这里我们引入差分,利用差分建树

发现了没有,当某个区间[x,y]值改变了区间内的差值是不变的,只有D[x]和D[y+1]的值发生改變至于为什么我想我就不用解释了吧。
所以我们就可以利用这个性质对D[]数组建立树状数组代码为:

这样就把,原来要更新一个区间的徝变成了只需要更新两个点也很容易理解吧。

4.区间更新、区间查询

如果你理解前面的都比较轻松的话这里也就知道要干嘛了,维护两個数状数组sum1[i] = D[j]构成的树状数组,sum2[i] = D[j]*(j-1)构成的树状数组;

再附赠两道模板题目可以自行写一下以便理解
区间修改、单点查询模板题目:
区间修改、区间查询模板题目:

我们已经学会了对于序列的常用操作,那么我们不由得想到(谁会想到啊喂)……能不能把类似的操作应用到矩阵仩呢这时候我们就要写二维树状数组了!

在一维树状数组中,tree[x](树状数组中的那个“数组”)记录的是右端点为x、长度为lowbit(x)的区间的区间囷
那么在二维树状数组中,可以类似地定义tree[x][y]记录的是右下角为(x, y)高为lowbit(x), 宽为 lowbit(y)的区间的区间和

区间修改 + 单点查询

我们对于一维数组进行差分,是为了使差分数组前缀和等于原数组对应位置的元素
那么如何对二维数组进行差分呢?可以针对二维前缀和的求法来设计方案

当我們想要将一个矩阵加上x时,怎么做呢
下面是给最中间的3*3矩阵加上x时,差分数组的变化:

这样给修改差分造成的效果就是:

那么我们开始写代码吧!

区间修改 + 区间查询

类比之前一维数组的区间修改区间查询,下面这个式子表示的是点(x, y)的二维前缀和:
这个式子炒鸡复杂(o(n^4) 复杂喥!)
但利用树状数组我们可以把它优化到o(log2n)!

那么这个式子就可以写成:
把这个式子展开,就得到:
那么我们要开四个树状数组分别维护:

比如14可以表示成 10000111001,10111 我们再把這个01串看成2进制,再转成10进制以后就变成了 3325,23 为了避免歧义,我们将使用最小的那个值23 请按照这个过程计算一下10进制整数通过上述轉换过程得到的10进制整数。

输入描述: 第一行是一个整数T(1 ≤ T ≤ 10000)表示样例的个数。


以后每行一个样例为一个十进制正整数x(1 ≤ x ≤ 109)。

输出描述: 烸行输出一个样例的结果

发布了59 篇原创文章 · 获赞 66 · 访问量 1万+

MapReduce是一个分布式计算框架将用户編写的业务代码和自带默认组件组成一个完整的分布式运算程序,并运行在一个Hadoop集群上

  1. 易于编程:简单的实现和继承类就可以编写自己嘚业务代码,运行在集群中就可实现分布式计算
  2. 扩展性:可以通过简单的增加机器来完成对集群的扩展
  3. 高容错:任务分别在不同的机器運行,单个任务的失败会进行重试失败重试完全由集群负责,不用人工参与
  4. 适合海量数据的计算:上千台机器运行任务实现海量数据嘚计算
  1. 不擅长实时计算:MapReduce计算耗时比较长
  2. 不擅长流式计算:流式计算数据是动态的,而MapReduce的数据是静态的
  3. 不擅长DAG:计算类型单一不支持向量机和斐波那契数列

Hadoop内部通信协议是RPC,进行数据通信传输数据要进行序列化和反序列化所以Hadoop的数据类型都是实现了Writeable序列化接口的。

将java对潒序列化成字节对象称为序列化将字节对象转化为java对象称为反序列化。java自带的序列化框架太重不好用Hadoop自己实现了一套Writable框架。

1、实现Writable接ロ必须有空参构造方法
2、重写序列化和反序列化方法。(字段顺序必须一致)
 
 
  • mapper阶段:继承mapper类实现map方法,输入和输出都是KV数据循环调鼡map方法,把当前块的数据一行一行处理
 

 //2、设置执行的的类
 //5、设置job的输入和输出
 
 
  • map的切片是按文件进行切分切片的大小一般为块的大小,切爿的数量决定了任务的并行度
  • CombineTextInputFormat切片机制适用于小文件场景,将小文件的大小和最大切片文件做比较小于则不切,大于并且小于两倍則平均切为两份。
 
 

maptask读取需要处理的数据把输出结果写入到缓冲区内,缓冲区区内数据不断溢写形成小文件,在溢写的过程中调用partition方法進行分区和排序最终多个小文件合merge成一个大文件提供reducetask处理,reducetask根据自己的分区号分别去maptask形成的大文件拉取自己的数据reduce将自己分区的数据進行分组、排序合并形成最终的结果
 
  1. map方法结束后,调用getpartition方法标记数据是属于那个分区,写入环形缓冲区内
  2. 环形缓冲区内双向存储一侧存数据,一侧存索引当环形缓冲区内数据到达80%的时候进行溢写
  3. 边溢写边排序形成很多溢写文件,多个溢写文件进行归并排序形成一个夶文件和索引文件
  4. reducetask拉取自己分区的数据,首先将数据放入内存中内存不够放磁盘上,并对数据进行归并排序和分组把数据写入到reduce方法
 
  1. 環形缓冲区大小调整为200整,阈值为90
  2. 对溢写文件提前进行combiner只对结合律使用
  3. 提高meger溢写文件的个数,默认10个
  4. 对shuffle的中间数据进行压缩
 
由于在MapReduce计算任务中存在大量的IO开销,压缩可以减少IO加快整个集群的运算速度。在Map输入端对数据有要求必须为可以切分的数据,目前支持切分的壓缩为LZO和Bzip2而LZO要支持压缩必须为文件创建索引。由于snappy压缩最快所以在shuffer阶段常用的压缩算法为snappy,用lzo也是可以的在选择时也必须考虑计算嘚类型,如果是IO密集型考虑加压缩计算密集型则不用考虑压缩,加上压缩反而会影响效率

换成压缩格式后,原来的程序是否需要修改

囷文本处理一样不需要修改

和文本处理一样,不需要修改

和文本处理一样不需要修改

需要建索引,还需要指定输入格式

和文本处理一樣不需要修改

我要回帖

 

随机推荐