C语言树状数组的实例详解
最近学了树状数组,给我的感觉就是 这个数据结构好神奇啊^_^
首先她的常数比线段树小,其次她的实现复杂度也远低于线段树 (并没有黑线段树的意思=-=)
所以熟练掌握她是非常有必要的。。
关于树状数组的基础知识与原理网上一搜一大堆,我就不赘述了,就谈一些树状数组的应用好了
1,单点修改,求区间和
#define lowbit(x) (x&-x) // 设 x 的末尾零的个数为 y , 则 lowbit(x) == 2^y void Update(int i,int v) // 初始化与单点修改 { while(i <= n) { c[i] += v ; i += lowbit(i) ; } } inline int Sum(int i) // 区间求和 { int res = 0 ; while(i > 0) { res += c[i] ; i -= lowbit(i) ; } return res ; }
2,区间修改,单点查询
这里要用到差分的思想
创建一个差分数组c[],令c[i] = a[i] - a[i-1] (a[i] 表示原本的第i个数)
则a[i] = ( a[i] - a[i-1] ) + ( a[i-1] - a[i-2] ) + ...... + ( a[2] - a[1] ) +a[1]
= c[i] + c[i-1] + ...... + c[2] + c[1]
所以单点查询变成了区间求和
那么区间修改怎么办呢 ?
我们看这样一个例子:
a 1 3 4 5 7 10
c 1 2 1 1 2 3
若我们令区间[2,4]加2,则
a 1 5 6 7 9 10
c 1 4 1 1 2 1
我们可以发现只有c[2]和c[5]的数值改变了,其实原理也很好想,区间内的前后元素差是不变的,只有(区间第一个元素与前一个元素的差) 和 (区间后第一个元素与区间末尾元素的差) 改变了。所以区间修改问题变成了单点修改问题。
for(int i=1;i<=n;i++) { a[i] = read() ; Update(i,a[i]-a[i-1]); } /* int x=0,y=0; // 注释掉的内容是空间上的优化(初学者建议先跳过) for(int i=1;i<=n;i++) { if(i%2) { x = read() ; Update(i,x-y); } else { y = read() ; Update(i,y-x) ; } } */ int ii ; int k,x,y; for(int i=1;i<=m;i++) { ii = read() ; if(ii == 1) { x = read() ; y = read() ; k = read() ; Update(x,k); Update(y+1,-k); } if(ii == 2) { x = read() ; printf("%d\n",Sum(x)); } }
(洛谷有对应的模板题 P3374 与 P3368)
上述就是树状数组最基础的两个应用,日后更深入的学习后再来更新。
如有疑问请留言或到本站社区交流讨论,感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
本文向大家介绍C语言 数据结构平衡二叉树实例详解,包括了C语言 数据结构平衡二叉树实例详解的使用技巧和注意事项,需要的朋友参考一下 数据结构平衡二叉树 参考代码如下: 运行结果如下: 感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
本文向大家介绍C语言模拟实现atoi函数的实例详解,包括了C语言模拟实现atoi函数的实例详解的使用技巧和注意事项,需要的朋友参考一下 C语言模拟实现atoi函数的实例详解 atoi函数,主要功能是将一个字符串转变为整数,例如将“12345”–>12345。但在实现过程中,我们难免会因为考虑不够全面而漏掉比较重要的几点,今天就总结一下实现atoi函数需要注意的地方。 1.指针为NULL 2.字符串
本文向大家介绍C语言 数组指针详解及示例代码,包括了C语言 数组指针详解及示例代码的使用技巧和注意事项,需要的朋友参考一下 数组(Array)是一系列具有相同类型的数据的集合,每一份数据叫做一个数组元素(Element)。数组中的所有元素在内存中是连续排列的,整个数组占用的是一块内存。以int arr[] = { 99, 15, 100, 888, 252 };为例,该数组在内存中的分布如下图所示
本文向大家介绍C语言转义字符实例详解,包括了C语言转义字符实例详解的使用技巧和注意事项,需要的朋友参考一下 在字符集中,有一类字符具有这样的特性:当从键盘上输入这个字符时,显示器上就可以显示这个字符,即输入什么就显示什么。这类字符称为可显示字符,如a、b、c、$、+和空格符等都是可显示字符。 另一类字符却没有这种特性。它们或者在键盘上找不到对应的一个键(当然可以用特殊方式输入),或者当按键以后不能
本文向大家介绍C语言栈的表示与实现实例详解,包括了C语言栈的表示与实现实例详解的使用技巧和注意事项,需要的朋友参考一下 1.基本概念: C语言的栈是指限定仅在表尾进行插入和删除操作的线性表。 栈作为C语言中一种常用的数据结构,是一种只能在一端进行插入和删除操作的特殊线性表。它按照先进后出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据(最后一个数据被第一
本文向大家介绍C语言中getch()函数详解及简单实例,包括了C语言中getch()函数详解及简单实例的使用技巧和注意事项,需要的朋友参考一下 C语言中getch()函数详解及简单实例 前言: 这个函数是一个不回显函数,当用户按下某个字符时,函数自动读取,无需按回车,有的C语言命令行程序会用到此函数做游戏,但是这个函数并非标准函数,要注意移植性! 所以有这样的一个接口,那就很牛逼了,至少可以做个游