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日

相关文章

  • Java 中很好用的数据结构(你绝对没用过)

    Java 中很好用的数据结构(你绝对没用过) 介绍 Java 中的数据结构有很多,比如数组、链表、栈、队列、堆、树等等。在这些常见的数据结构中,我们或多或少都会使用到。但是本篇文章要讲述的是一些比较冷门,但是很好用的数据结构。 双向队列(Deque) 双向队列,顾名思义,是一种可以双向操作的队列。它可以从队列的两端插入和删除元素,因此常被用作实现栈和队列以及…

    数据结构 2023年5月17日
    00
  • Java 数据结构算法Collection接口迭代器示例详解

    Java 数据结构算法 Collection 接口迭代器示例详解 如果你正在学习 Java 编程,那么数据结构和算法一定是一个不可避免的话题。在 Java 中,Collection 框架提供了许多有用的接口和类来管理和操作集合。其中,迭代器 Iterator 是 Collection 中最重要的接口之一,它提供了对集合元素进行迭代的方法。本文将对 Java …

    数据结构 2023年5月17日
    00
  • C语言深入讲解链表的使用

    C语言深入讲解链表的使用 什么是链表? 链表是一种常用的数据结构,它的存储方式是通过指针相互连接实现的。链表是由若干个节点(node)构成的,每个节点都存储着一些信息和指向下一个节点的指针。 链表实现的基本操作 链表的基本操作包括插入节点、删除节点以及遍历链表。我们下面将通过代码示例详细介绍这些操作。 插入节点 链表的插入节点操作是指在链表的某一位置插入一个…

    数据结构 2023年5月17日
    00
  • 数据结构中的各种排序方法小结(JS实现)

    数据结构中的各种排序方法小结(JS实现) 本文将介绍常见的八种排序算法: 冒泡排序 插入排序 选择排序 快速排序 归并排序 堆排序 希尔排序 计数排序 下面进行详细讲解。 冒泡排序 冒泡排序是一种简单的排序算法,它重复地遍历数组,比较相邻的两个元素,并按大小交换位置,一直到整个数组排序完成。它的时间复杂度为O(n^2)。 示例代码: function bub…

    数据结构 2023年5月17日
    00
  • C语言数据结构与算法时间空间复杂度基础实践

    C语言数据结构与算法时间空间复杂度基础实践攻略 基本概念 时间复杂度:算法在执行时所需要的基本操作数,通常用O(n)表示,其中n是输入数据的规模。时间复杂度越小,算法执行所需要的时间越少,算法效率越高。 空间复杂度:算法在执行时所需要的额外空间数,通常用O(S)表示,其中S是额外的空间数。空间复杂度越小,所需的额外空间越少,算法的内存效率越高。 实践步骤 1…

    数据结构 2023年5月17日
    00
  • 深入理解Objective-C中类的数据结构

    深入理解Objective-C中类的数据结构 在Objective-C中,类作为面向对象编程的基础,是必不可少的概念。理解Objective-C中类的数据结构,对于开发者理解iOS应用程序的底层原理,以及编写高质量代码具有重要的意义。 类的数据结构 一个Objective-C类由以下几部分组成: isa指针:指向该类对象的元类,元类是描述一个类的对象。isa…

    数据结构 2023年5月17日
    00
  • 柏林噪声算法(Perlin Noise)

    概述 引述维基百科的介绍: Perlin噪声(Perlin noise,又称为柏林噪声)指由Ken Perlin发明的自然噪声生成算法,具有在函数上的连续性,并可在多次调用时给出一致的数值。 在电子游戏领域中可以透过使用Perlin噪声生成具连续性的地形;或是在艺术领域中使用Perlin噪声生成图样。 维基百科的介绍相当的官方,其实可以理解为一个随机函数,不…

    算法与数据结构 2023年4月17日
    00
  • C++实现KDTree 附完整代码

    对于“C++实现KDTree 附完整代码”的攻略,我会分为以下几个部分进行讲解: KDTree的基本概念和算法原理 KDTree的实现思路和整体代码结构 KDTree在实际应用中的应用场景 两个示例应用说明 KDTree基本概念和算法原理 KDTree全称是K-Dimensional Tree,即K维树,是一种便于高维空间数据检索的数据结构。其基本思路是对于…

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