首页 > 编程语言 >算法之树状数组详解

算法之树状数组详解

时间:2024-10-26 17:19:29浏览次数:3  
标签:树状 int tree private 算法 详解 数组 public size

树状数组

树状数组(Binary Indexed Tree,简称BIT),也被称为Fenwick树,是一种用于处理数组问题的高效数据结构。它特别适合解决涉及区间查询和更新的问题,尤其是当需要频繁地计算数组的前缀和时。树状数组的核心思想是利用二进制表示法(lowbit函数)来快速定位数组中的区间,并在O(log n)时间内完成单点更新和区间查询操作。(树状数组解决的题目,也能用线段树解决(反过来不一定)。但树状数组实现简单,代码短。)

树状数组的基本操作:
更新操作(单点更新)
对于数组中的第 i 个元素,更新树状数组中所有包含该元素的区间。
查询操作(区间查询)
查询数组中从第 i 个元素到第 j 个元素的累积和。
基础知识
lowbit(x)计算——lowbit(x) 可以通过位运算来高效计算。对于一个整数 x,x & (-x) 操作的结果就是 x 的二进制表示中最低位的1。这是因为 -x 的二进制表示中,x 的所有位都被取反,然后加1,这样 x 的最低位的1就变成了0,而其他位都是1。因此,x & (-x) 操作实际上就是将 x 与一个只有 x 最低位的1为1,其他位都是0的数进行与操作。

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

单点更新区间查询

public class BinaryIndexedTree {
    private int[] tree;
    private int size;

    public BinaryIndexedTree(int size) {
        this.size = size;
        tree = new int[size + 1];
    }

    // 计算小于等于i的最大2的幂次方
    private int lowbit(int i) {
        return i & (-i);
    }

    // 单点更新,增加tree[i]的值
    public void update(int i, int val) {
        while (i <= size) {
            tree[i] += val;
            i += lowbit(i);
        }
    }

    // 区间查询,计算[1, i]区间的累积和
    public int query(int i) {
        int sum = 0;
        while (i > 0) {
            sum += tree[i];
            i -= lowbit(i);
        }
        return sum;
    }

    // 区间查询,计算[l, r]区间的累积和
    public int query(int l, int r) {
        return query(r) - query(l - 1);
    }
}

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

单点修改单点查询

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

区间修改单点查询

public class FenwickTree {
    private int[] tree;
    private int[] values;
    private int size;

    // 构造函数,初始化树状数组和值数组的大小
    public FenwickTree(int size) {
        this.size = size;
        tree = new int[size + 1];
        values = new int[size + 1];
    }

    // 计算小于等于i的最大2的幂次方
    private int lowbit(int i) {
        return i & (-i);
    }

    // 更新树状数组,反映值的变化
    private void updateTree(int i) {
        while (i <= size) {
            tree[i] += values[i];
            i += lowbit(i);
        }
    }

    // 区间修改,对区间[L, R]内每个元素增加val
    public void rangeUpdate(int L, int R, int val) {
        values[L] += val;
        if (R + 1 <= size) {
            values[R + 1] -= val;
        }
        updateTree(L);
        updateTree(R + 1);
    }

    // 单点查询,查询位置i的值
    public int query(int i) {
        int sum = 0;
        while (i > 0) {
            sum += tree[i];
            i -= lowbit(i);
        }
        return values[i] + sum;
    }
}

区间修改区间查询

在这里插入图片描述

在这里插入图片描述

307. 区域和检索 - 数组可修改

class NumArray {
    private int[] nums;
    private int[] tree;

    public NumArray(int[] nums) {
        int n = nums.length;
        this.nums = new int[n]; // 使 update 中算出的 delta = nums[i]
        tree = new int[n + 1];
        for (int i = 0; i < n; i++) {
            update(i, nums[i]);
        }
    }

    public void update(int index, int val) {
        int delta = val - nums[index];
        nums[index] = val;
        for (int i = index + 1; i < tree.length; i += i & -i) {
            tree[i] += delta;
        }
    }

    private int prefixSum(int i) {
        int s = 0;
        for (; i > 0; i &= i - 1) { // i -= i & -i 的另一种写法
            s += tree[i];
        }
        return s;
    }

    public int sumRange(int left, int right) {
        return prefixSum(right + 1) - prefixSum(left);
    }
}

标签:树状,int,tree,private,算法,详解,数组,public,size
From: https://blog.csdn.net/w287586/article/details/143106434

相关文章

  • 【路径规划】基于蚁群算法的二维机器人路径规划,二维珊格地图路径规划
    摘要本文研究了基于蚁群算法的二维机器人路径规划问题,利用蚁群算法优化机器人在二维栅格地图中的最优路径。蚁群算法通过仿生学模拟蚂蚁寻找食物的过程,在障碍物密集的栅格地图中寻找出最短、最优的路径。实验结果表明,该算法能够有效地避开障碍物,并通过多次迭代逐步优化路径,......
  • 【无人机设计与控制】基于Astar算法无人机路径规划,优化路径平滑
    摘要本文提出了一种基于A算法的无人机路径规划方法,并通过路径平滑优化提升路径的可行性和安全性。传统A算法在生成路径时,常因路径节点分布不规则导致路径不平滑,影响无人机的飞行效率和安全性。本文通过引入贝塞尔曲线对A*算法生成的路径进行优化,使其更加平滑和符合无人机的......
  • 【算法优化】混合策略改进的蝴蝶优化算法
    摘要蝴蝶优化算法(ButterflyOptimizationAlgorithm,BOA)是一种新兴的智能优化算法,其灵感来自蝴蝶的觅食行为。本文基于经典BOA,通过引入混合策略进行改进,从而提高其在全局寻优和局部搜索中的性能。实验结果表明,改进的蝴蝶优化算法(IBOA)在处理复杂多模态函数优化问题时表......
  • 【源码+论文】Java毕业设计:基于SpringBoot协同过滤算法的汽车推荐网站(Mysql数据库)
    ✅更多源码|课设......
  • 数据结构与算法——顺序栈的实现
    数据结构栈——一列数据,表尾入栈,表尾出栈,类似于子弹弹匣,压入子弹和拿出子弹都是从最上方进出。结构体structStack{ int*arr; intcapacity;//数组容量 inttop;//存储栈顶元素的下标};初始化栈intInitStack(structStack*stack){ stack->arr=......
  • 文件操作详解
    目录1.为什么使⽤⽂件?2.什么是⽂件?2.1程序⽂件2.2数据⽂件2.3⽂件名3.⼆进制⽂件和⽂本⽂件?4.⽂件的打开和关闭4.1流和标准流4.1.1流4.1.2标准流4.2⽂件指针4.3⽂件的打开和关闭5.⽂件的顺序读写5.1顺序读写函数介绍5.2对⽐⼀组函数:6.⽂件的随......
  • 动态内存管理详解
    目录1.为什么要有动态内存分配2.malloc和free2.1malloc2.2free3.calloc和realloc3.1calloc3.2realloc4.常⻅的动态内存的错误4.1对NULL指针的解引⽤操作4.2对动态开辟空间的越界访问4.3对⾮动态开辟内存使⽤free释放4.4使⽤free释放⼀块动态开辟内存的......
  • USB协议详解第22讲(USB包-数据包及重传机制)
    USB协议详解第22讲(USB包-数据包及重传机制)1.数据包的分类数据类包有DATA0数据包、DATA1数据包、DATA2数据包、DATAM数据包。2.数据类包的组成我们今天看数据类包的详细结构,数据包的内容由PID域+数据域+16bitCRC域组成,下图为数据包各个域和抓包协议的对应图。3.数据包的功能......
  • Win11系统appdata文件夹位置详解
    Win11系统appdata文件夹位置详解在我们的日常电脑使用中,C盘作为系统盘,承载着大量的系统文件和应用程序数据。其中,Appdata文件夹是一个非常重要的目录,它包含了软件的配置信息、临时文件等,这些文件对于软件的正常运行至关重要。然而,由于Appdata文件夹默认是隐藏的,很多使用Win......
  • 初识算法 · 二分查找(4)
    目录前言:寻找峰值题目解析算法原理算法编写寻找旋转排序数组中的最小值题目解析算法原理算法编写寻找缺失的数字题目解析算法原理算法编写前言:​本文的主题是二分查找,通过三道题目讲解,一道是寻找峰值,一道是搜索旋转排序数组的最小值,一道是0-n-1中缺失的数字......