C语言树状数组的实例详解

 更新时间:2017年10月15日 16:58:46   作者:zubizakeli  
这篇文章主要介绍了C语言树状数组的实例详解的相关资料,希望通过本文能帮助到大家,让大家理解掌握这部分内容,需要的朋友可以参考下

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语言详解链式队列与循环队列的实现

    队列(Queue)与栈一样,是一种线性存储结构,它具有如下特点:队列中的数据元素遵循“先进先出”(First In First Out)的原则,简称FIFO结构。在队尾添加元素,在队头删除元素,本篇来讲解链式队列与循环队列的实现
    2022-04-04
  • C++的template模板中class与typename关键字的区别分析

    C++的template模板中class与typename关键字的区别分析

    这篇文章中我们来谈一谈C++的template模板中class与typename关键字的区别分析,同时会讲到嵌套从属名称时的一些注意点,需要的朋友可以参考下
    2016-06-06
  • C++模板非类型形参的详细讲解

    C++模板非类型形参的详细讲解

    这篇文章主要给大家介绍了关于C++模板非类型形参的相关资料,文中通过实例代码介绍的非常详细,对大家的学习或者工作就有一定的参考学习价值,需要的朋友可以参考下
    2021-11-11
  • C语言 typedef:给类型起一个别名

    C语言 typedef:给类型起一个别名

    本文主要介绍C语言 typedef,这里整理了相关资料及简单示例代码帮助大家学习理解,有兴趣的小伙伴可以参考下
    2016-08-08
  • Qt中PaintEvent绘制实时波形图的实现示例

    Qt中PaintEvent绘制实时波形图的实现示例

    本文主要介绍了Qt中PaintEvent绘制实时波形图的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-06-06
  • c语言中形参与实参的关系解读

    c语言中形参与实参的关系解读

    这篇文章主要介绍了c语言中形参与实参的关系,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-07-07
  • C++ OpenCV实战之手写数字识别

    C++ OpenCV实战之手写数字识别

    这篇文章主要为大家详细介绍了如何使用machine learning机器学习模块进行手写数字识别功能,文中的示例代码讲解详细,感兴趣的可以了解一下
    2022-08-08
  • 在C语言编程中使用变量的基础教程

    在C语言编程中使用变量的基础教程

    这篇文章主要介绍了在C语言编程中使用变量的基础教程,特别需要注意C语言中的指针变量,需要的朋友可以参考下
    2016-02-02
  • C++实现顺序表的方法

    C++实现顺序表的方法

    本文给大家带来了C++实现顺序表的方法,代码简单易懂,附有注释,感兴趣的朋友一起看下吧
    2016-08-08
  • C++名称空间特性

    C++名称空间特性

    这篇文章主要介绍了C++名称空间特性,文章围绕C++名称空间特性的相关资料展开详细内容,需要的小伙伴可以参考一下下文具体内容,希望对你的学习有所帮助
    2022-01-01

最新评论