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

首先需要了解什么是树状数组。树状数组(Binary Indexed Tree,BIT),也叫做 Fenwick 树(树状数组的发明者是Peter M. Fenwick),是一个查询和修改复杂度都为 log(n) 的数据结构,与线段树类似,但使用起来比线段树更加方便以及简洁。

在该攻略中,我们将通过两条树状数组的实例,详细讲解树状数组,让读者更好地理解树状数组的基本原理和应用。

示例一:树状数组求和

首先我们介绍一下树状数组的基本结构:

int lowbit(int x) {
    return x & -x;
}

int c[maxn]; // 树状数组

其中lowbit是一个辅助函数,用来计算一个数的二进制表示下最低位的1所对应的数。即lowbit(x) = x & -x

c数组用于存储树状数组。

接下来,我们来看一个求和的例子。假设我们有一个长度为n的数组a

int a[maxn], c[maxn];
int n;

我们希望支持对a数组的区间求和,增加单个元素,查询单个元素等操作。我们可以使用树状数组来实现这些操作。具体的实现如下:

int lowbit(int x) {
    return x & -x;
}

int c[maxn]; // 树状数组

void update(int x, int v) {
    while(x <= n){
        c[x] += v;
        x += lowbit(x);
    }
}

int query(int x) {
    int ans = 0;
    while(x){
        ans += c[x];
        x -= lowbit(x);
    }
    return ans;
}

其中,update函数用来增加某个位置上的值,query函数用来查询一个区间的和。例如,要修改第i个位置上的元素,需要调用update(i, v)方法。而要求1~j的区间和,则需要调用query(j) - query(i - 1)方法。

例如,对于一个数组a = {1,2,3,4,5},我们可以先初始化树状数组:

for(int i = 1; i <= n; i++){
    update(i, a[i]);
}

接下来,我们可以调用query函数得到区间和:

int sum = query(j) - query(i - 1)

示例二:树状数组求逆序对

接下来,我们给出第二个例子:树状数组求逆序对。

逆序对的定义是,对于一个序列,如果 a[i] > a[j],且 i < j,则称 (i, j) 为一个逆序对。求解逆序对的个数是一个常见的问题。

我们可以使用树状数组来实现求逆序对的过程。具体实现如下:

const int maxn = 500010;
int a[maxn], c[maxn], n;

inline int lowbit(int x){
    return x & (-x);
}

void add (int x, int v) {
    for (int i = x; i <= n; i += lowbit(i)){
        c[i] += v;
    }
}

int sum (int x) {
    int ans = 0;
    for (int i = x; i > 0; i -= lowbit(i)){
        ans += c[i];
    }
    return ans;
}

int main() {
    scanf("%d", &n);
    for (int i = 1; i <= n; i++){
        scanf("%d", &a[i]);
    }
    int ans = 0;
    for (int i = n; i > 0; i--){
        ans += sum(a[i] - 1);
        add(a[i], 1);
    }
    printf("%d\n", ans);
    return 0;
}

具体的实现如下:

  • 先从后往前遍历序列,每遍历到一个数,就把它放到树状数组中,并且统计一下在它之前小于它的数的个数,即sum(a[i] - 1)
  • 最终的答案即为累加得到的逆序对数。

例如,对于一个序列a = {3, 1, 2},我们可以先初始化树状数组:

for(int i = n; i > 0; i--){
    add(a[i], 1);
}

然后就可以累加逆序对数:

int ans = 0;
for (int i = n; i > 0; i--){
    ans += sum(a[i] - 1);
}
printf("%d\n", ans);

通过以上两个例子,我们可以看到树状数组在数据结构和算法中的广泛应用。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C语言树状数组的实例详解 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • C语言数据结构系列之树的概念结构和常见表示方法

    C语言数据结构系列之树的概念结构和常见表示方法 树是一种非线性数据结构,它由若干个节点构成,节点之间通过边来连接,具有层次关系。 树的基本概念和术语 节点:树中的元素,它可以包含一个数据元素或多个数据元素,一个节点也可以称为一个分支节点。 根节点:树的最上层节点,它没有父节点。 叶子节点:没有子节点的节点称为叶子节点。 父节点和子节点:父节点是某个节点的上一…

    数据结构 2023年5月17日
    00
  • C语言 超详细总结讲解二叉树的概念与使用

    C语言 超详细总结讲解二叉树的概念与使用 1. 什么是二叉树? 二叉树是一种树状数据结构,其中每个节点最多有两个子节点,被称为左子节点和右子节点。具有以下几个特点: 每个节点最多有两个子节点; 左子节点可以为空,右子节点也可以为空; 二叉树的每个节点最多有一个父节点; 二叉树通常定义为递归模式定义,即每个节点都可以看做一棵新的二叉树。 2. 二叉树的遍历方式…

    数据结构 2023年5月17日
    00
  • java数据结构与算法数组模拟队列示例详解

    下面是“java数据结构与算法数组模拟队列示例详解”的完整攻略。 标题 Java数据结构与算法:数组模拟队列示例详解 简介 本文将以Java语言为例,详细讲解如何使用数组模拟队列。对于初学者来说,队列是一个非常基础的数据结构,掌握其实现方法可以帮助进一步理解其他的数据结构和算法。 队列的定义 队列(Queue)是一种先进先出(First In First O…

    数据结构 2023年5月17日
    00
  • C++ 数据结构之kmp算法中的求Next()函数的算法

    C++ 数据结构之kmp算法中的求Next()函数的算法 什么是KMP算法和Next()函数 KMP算法(Knuth-Morris-Pratt算法)是一种字符串匹配算法,能够解决的问题是,在一个文本串S中查找一个模式串P是否出现并且返回第一次出现的位置。而Next()函数则是在KMP算法中使用的一个关键的子函数,用于计算模式串P中每个前缀的最长相同真前缀和后…

    数据结构 2023年5月17日
    00
  • Python数据结构之二叉排序树的定义、查找、插入、构造、删除

    Python数据结构之二叉排序树 一、定义 二叉排序树(Binary Search Tree,BST),也称为二叉查找树或二叉搜索树,是一种基于二叉树的数据结构,其中每个节点都包含一个键值,且满足: 左子树中所有节点的键值均小于当前节点; 右子树中所有节点的键值均大于当前节点; 这是一种自平衡的数据结构,可以快速地进行查找、插入、删除等操作。 二、查找 查找…

    数据结构 2023年5月17日
    00
  • Java深入了解数据结构之哈希表篇

    Java深入了解数据结构之哈希表篇 1. 哈希表的定义 哈希表(Hash Table),也叫散列表,是根据关键码值(Key Value)而直接进行访问的数据结构。通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做哈希函数(Hash Function)。 哈希表是基于哈希函数实现的,哈希函数将关键字映射到哈希表中的位置,如果存在两个…

    数据结构 2023年5月17日
    00
  • 排序算法之详解选择排序

    引入 选择排序顾名思义是需要进行选择的,那么就要问题了,选择到底是选择什么呢? 选择排序的选择是选择数组中未排序的数组中最小的值,将被选择的元素放在未排序数组的首位 如果你对 ‘未排序数组’ , ‘选择’ 的概念不理解,那么你可以看看下面的图 思路 有了上面的一些基础之后,我们再来说说选择排序算法的思路 不断的选择未排序数组中最小的值,将其与未排序数组的首位…

    算法与数据结构 2023年4月25日
    00
  • Java数据结构之链表相关知识总结

    Java数据结构之链表相关知识总结 链表是一种非常常用的数据结构,它有许多实际应用,比如链表可以用来实现栈、队列、散列表和图等数据结构。在Java语言中,链表的实现方式主要有单向链表、双向链表和循环链表。 单向链表 单向链表是一种链表结构,每个节点包含两个元素:节点值和一个指向下一个节点的引用。链表的头结点(第一个节点)不包含值,仅包含指向链表中第一个实际节…

    数据结构 2023年5月17日
    00
合作推广
合作推广
分享本页
返回顶部