其他分享
首页 > 其他分享> > 树状数组课件——Skywalker

树状数组课件——Skywalker

作者:互联网

树状数组(Binary Indexed Tree)

Author: 朱胜豪

Creation time:2021/8/10 21:28

Last update:2021/8/12 21:10

目录

情景引入


在处理一段区间的和的时候,我们可以通过前缀和算法来提高运算效率,除去预处理,能做到每次询问$o(1)$​​算出,这个时间复杂度是极其优秀的,但是如果修改一个点后,再次询问一段区间的和,我们发现,最坏情况下,我们要更新$n$​次数组,我们不能接受。那么,如何快速的询问一段区间的长度,并且修改的时候更新速度也要足够优秀,这时候,就体现出了树状数组算法的优越性。

即:能以$o(logn)$的时间复杂度进行单点修改,以$o(logn)$的时间复杂度进行区间查询。

$log$​级别的算法是极其可靠的。$2^{31} log$​后也不过是$31$​而已(这边的$log$是以$2$为底)。

前置知识


顾名思义,树状数组是根据树形结构来优化运算,从而达到可观的时间复杂度,我们需要一些工具来进行遍历树的每个节点,来方便我们的运算。

lowbit函数的定义:lowbit函数的作用是返回二进制下最后一位$1$​代表的十进制数,例如:$12(1100)$​,那么他的最后一位$1$​所代表的十进制数就是 $4(100)$​。

lowbit函数的实现:

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

lowbit函数的证明:
$$
设x的最低位的1在第k位,那么0~k - 1位都是0\
-x = (\sim x + 1)取反加一,取反后0 \sim k -1都会变成1,+1后,则0 \sim k-1又消成了0\
第k位变成1,前面都是原来的取反的结果,则为一个零,一个一,取与后为0\
得证\
$$

lowbit只是一个工具,证明有兴趣可以考虑,无兴趣可看可不看。

树状数组


铺垫了一点点,下面来到我们的树状数组,下面将从:树状数组的理论基础,树状数组的代码实现,树状数组的用途来进行叙述。

树状数组的理论基础:

树状数组 = 前缀和 + 二进制拆分

img

以上性质来自算法进阶指南.

$$
c[x]保存的是序列a的区间[x - lowbit + 1 , x]的和\
即:\sum_{i = x - lowbit(x) - 1}^xa[i]
$$

树状数组的代码实现:
树状数组支持的基本操作是查询前缀和,即序列第1~x个数的和,[1 , x]已经被划分成了$log(N)$​个小区间,而每个区间,都在$c$​数组中,所以查询区间前缀和的代码如下,其时间复杂度为$O(logN)$​.

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

当然,如果查询$l \sim r$​的前缀和,我们可以利用前缀和思想,$query(r) - query(l - 1)$​​

树状数组支持的第二个操作是单点增加,在$x$位置加上value后,树状数组只需要$log(N)$的时间复杂度,维护树状结构和其性质。

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

至此,树状数组的两大基础操作,已经全部概述完毕,下面是树状数组的应用。

树状数组的应用:

若$i < j$​​​,且$a[i] > a[j]$​​​,则称$a[i]$​​与$a[j]$​​​​构成逆序对,我们已知的逆序对求法较为优秀的算法是归并排序,然而,树状数组也可以做到。

可以正序求出逆序对,也可以逆序遍历求出逆序对,这边给出的是逆序求逆序对的方法。

  1. 在序列$a$的数值范围上建立树状数组,对于每个$a[i]$,累加到答案$ans$中。
  2. 执行单点增加操作,把位置$a[i]$​上出现的数加上1,相当于($tr[a[i]] ++$​)。
for(int i = n; i ; i --)
{
    ans += query(a[i] - 1);
    add(a[i] , 1);
}
  1. ans即为所求

树状数组的拓展应用:

利用差分知识,我们可以维护区间修改,单点查询,篇幅有限,这里不展开了。

练习题目

题目集:https://vjudge.ppsucxtt.cn/contest/452921#overview

题目集密码:HPUACM

请尽量交在题目集中
题目名称 考察知识点
Sort it(例题1) 树状数组求逆序对
Inversion 离散化,树状数组求逆序对
敌兵布阵(例题2) 树状数组模版题
Japan 树状数组求逆序对
Matrix 二维树状数组
A Simple Problem with Integers 树状数组+差分+推公式
Stars 树状数组求逆序对
Mobile phones 二维树状数组
Bubble Sort 树状数组,思维
空间大师 树状数组,二分

例题1代码:

#include <bits/stdc++.h>
#define lowbit(x) (x & (-x))
using namespace std;
typedef long long LL;
const int N = 1000;

int n;
int a[N + 10];
LL tr[N + 10];

LL query(int x)
{
    LL ans = 0;
    for(int i = x;i >= 1;i -= lowbit(i)) ans += tr[i];
    return ans;
}

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

int main()
{
    while(~scanf("%d" , &n))
    {
        LL ans = 0;
        memset(tr , 0 , sizeof tr);
        for(int i = 1;i <= n;i ++) scanf("%d" , &a[i]);
        for(int i = n; i ;i --)
        {
            ans += query(a[i] - 1);
            add(a[i] , 1);
        }
        printf("%lld\n" , ans);
    }
    return 0;
}

例题2代码

#include <bits/stdc++.h>
#define lowbit(x) (x & (-x))
using namespace std;
typedef long long LL;
const int N = 50010;

int n , t;
int a[N];

LL tr[N + 10];

LL query(int x)
{
    LL ans = 0;
    for(int i = x;i >= 1;i -= lowbit(i)) ans += tr[i];
    return ans;
}

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

int main()
{
    scanf("%d" , &t);
    for(int ii = 1;ii <= t;ii ++)
    {
        memset(tr , 0 , sizeof tr);
        
        scanf("%d" , &n);
        for(int i = 1;i <= n;i ++)
        {
            scanf("%d" , &a[i]);
            add(i , a[i]);
        }
        
        printf("Case %d:\n" , ii);
        
        int x , y;
        string op; 
        while(cin >> op)
        {
            if(op == "End") break;
            scanf("%d %d" , &x, &y);
            
            if(op == "Query") printf("%lld\n" , query(y) - query(x - 1));
            else if(op == "Sub") add(x , -y);
            else if(op == "Add") add(x , y);
        }
    }
    return 0;
}

参考资料


资料:

【树状数组——百度百科】

【lowbit()的原理及证明】

算法进阶指南——李煜东

没参考,看着写的不错,推荐下

【知乎——算法学习笔记】

视频(墙裂推荐):
【18级李强会长b站视频】

标签:树状,int,lowbit,Skywalker,课件,数组,ans,逆序
来源: https://www.cnblogs.com/walkonthesky/p/15143073.html