ACM树状数组基础知识

1.先行知识

首先介绍lowbit(x)函数

lowbit(x)函数:lowbit(i)的意思是将i转化成二进制数之后,只保留最低位的1及其后面的0,截断前面的内容,然后再转成10进制数比如lowbit(7),7的二进制位是111lowbit(7) = 1,6 = 110(2),lowbit(6) = 2,同理lowbit(4) = 4,lowbit(12) = 4,lowbit(2) = 2,lowbit(8) = 8。

具体计算方法:lowbit(x)=x&(-x);

我们知道,计算机在进行运算的时候采用的是补码,这里我们先来介绍一下原码,补码,和反码;

原码

原码就是符号位加上真值的绝对值, 即用第一位表示符号, 其余位表示值. 比如如果是8位二进制:

[+1] = 0000 0001;[-1]=1000 0001;

 第一位是符号位. 因为第一位是符号位, 所以8位二进制数的取值范围就是:1111 1111 ~0111 1111,即-127~127,原码是人脑最容易理解和计算的方式。

反码

反码的表示方法:正数的反码是本身,负数的反码在器原码的基础上,符号位不变,其余各位取反。

[+1] = [0000 0001]=[00000001]

[-1]=[1000 0001]=[1111 1110]

补码

补码的表示方法:正数的补码就是其本身,负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1)

[+1] = [0000 0001]=[00000001]

[-1]=[1000 0001]=[1111 1111]

现在窝萌可以来用计算方法中的公式来计算lowbit(x)的值了,现在我们计算lowbit(12)的值,12的二进制数表示为0000 1100,由文章开头的那种做法我们可以得到lowbit(12)=100(2),即为4,现在我们使用x&(-x)来计算一下,12的补码为0000 1100,-12补码为1111 0100,对这两个二进制数求与运算,得0000 0100,和第一种计算的方法得出的结果是相同的。

求lowbit(x)的代码:

1 int lowbit(x) 
2 {   
3     return x & -x;
4 }

2.树状数组

首先我们搞明白树状数组是用来干嘛的,现在有一个这样的问题:有一个数组a,下标从0到n-1,现在给你w次修改,q次查询,修改的话是修改数组中某一个元素的值;查询的话是查询数组中任意一个区间的和,w + q < 500000。

这个问题很常见,首先分析下朴素做法的时间复杂度,修改是O(1)的时间复杂度,而查询的话是O(n)的复杂度,总体时间复杂度为O(qn);可能你会想到前缀和来优化这个查询,我们也来分析下,查询的话是O(1)的复杂度,而修改的时候修改一个点,那么在之后的所有前缀和都要更新,所以修改的时间复杂度是O(n),总体时间复杂度还是O(qn)O。

可以发现,两种做法中,要么查询是O(1),修改是O(n);要么修改是O(1),查询是O(n)。那么就有没有一种做法可以综合一下这两种朴素做法,然后整体时间复杂度可以降一个数量级呢?有的,对,就是树状数组。

 

转载于:https://www.cnblogs.com/zdy111/p/11148930.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值