透析 树状数组

本文详细介绍了一种名为树状数组的数据结构,它支持O(log n)时间复杂度的查询与更新操作。通过具体实例展示了如何使用树状数组解决实际问题,如高效计算序列的逆序数奇偶性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >



 

 

简单地研究了一下这个数据结构,在这做个总结摘要。

 

树状数组是一个查询和修改复杂度都为log(n)的数据结构,假设数组a[1...n],那么查询a[1] + …… + a[i] 的时间是log级别的,而且是一个在线的数据结构,支持随时修改某个元素的值,复杂度也为log级别。

 

来观察一下这个图:

 

令这棵树的结点编号为C1C2……Cn。令每个结点的值为这棵树的值的总和,那么容易发现:

C1 = A1

C2 = A1 + A2

C3 = A3

C4 = A1 + A2 + A3 + A4

C5 = A5

C6 = A5 + A6

C7 = A7

C8 = A1 + A2 + A3 + A4 + A5 + A6 + A7 + A8

……

C16 = A1 + A2 + A3 + A4 + A5 + A6 + A7 + A8 + A9 + A10 + A11 + A12 + A13 + A14 + A15 + A16

 

这里有一个有趣的性质,下午推了一下发现:

设节点编号为x,那么这个节点管辖的区间为2^k(其中kx二进制末尾0的个数)个元素。因为这个区间最后一个元素必然为Ax,所以很明显:

Cn = A(n – 2^k + 1) +…… + An

算这个2^k有一个快捷的办法,定义一个函数如下即可:

int lowbit(int x){

return x & (x ^ (x – 1));

}

查询

当想要查询一个SUM(n)时,可以依据如下算法即可:

Cn = A(n – 2^k + 1) +…… + An;

Sum(n) = A1+A2+A3+…+An = Cn+C[n-lowbit(n)]+C[(n-lowbit(n))-lowbit(n-lowbit(n))]+…;

step1: 令sum = 0,转第二步;

step2: 假如n <= 0,算法结束,返回sum值,否则sum = sum + Cn,转第三步;

step3: n = n – lowbit(n),转第二步。

 

可以看出,这个算法就是将这一个个区间的和全部加起来,为什么是效率是log(n)的呢?以下给出证明:

n = n – lowbit(n)这一步实际上等价于将n的二进制的最后一个1减去。而n的二进制里最多有log(n)1,所以查询效率是log(n)的。

修改

那么修改呢,修改一个节点,必须修改其所有祖先,最坏情况下为修改第一个元素,最多有log(n)的祖先。所以修改算法如下(给某个结点i加上x):

step1:i > n时,算法结束,否则转第二步;

step2: Ci = Ci + x i = i + lowbit(i)转第一步。

 

i = i +lowbit(i)这个过程实际上也只是一个把末尾1补为0的过程。

//修改过程必须满足减法规则!

 

所以整个程序如下:

int lowbit(int t){ 

    return t & (t^(t-1)); 

}

void modify(int pos,int num)

{

    while (pos<=n) {

        in[pos]+=num;

        pos+=lowbit(pos);

    }

}

int query(int end)

{

    int sum=0;

    while (end>0) {

        sum+=in[end];

        end-=lowbit(end);

    }

    return sum;

}

memset(in,0,sizeof(in)); //初始化

for (i=1;i<=n;i++) modify(i,a[i]);

 

 

以下拿这次上海预选赛的一道题做为一个例子好了。

题意:求一个序列逆序数的奇偶性。

如果初看此题,大概要乐死了,不是很轻松?看看限制条件吧:n <= 1000,000,数为1...n

内存限制:5MB

嗯……这下好了,随便怎么做都超内存。

数状数组怎么解决呢?

首先来看一下一个数的逆序数怎么求?一个数的逆序数为排在其前面又比其大的数的个数总和。

那么可以这么做:每查到一个数时,总能知道现在已经插入了多少个数,利用树状数组,可以很轻松地知道比它小的数有多少个,那么这个数的逆序数不是手到擒来?

此题只求奇偶性,所以开一个布尔数组是最省空间的,读完所有数之后,答案也就出来了。

 

 

内容概要:本文档详细介绍了Analog Devices公司生产的AD8436真均方根-直流(RMS-to-DC)转换器的技术细节及其应用场景。AD8436由三个独立模块构成:轨到轨FET输入放大器、高动态范围均方根计算内核和精密轨到轨输出放大器。该器件不仅体积小巧、功耗低,而且具有广泛的输入电压范围和快速响应特性。文档涵盖了AD8436的工作原理、配置选项、外部组件选择(如电容)、增益调节、单电源供电、电流互感器配置、接地故障检测、三相电源监测等方面的内容。此外,还特别强调了PCB设计注意事项和误差源分析,旨在帮助工程师更好地理解和应用这款高性能的RMS-DC转换器。 适合人群:从事模拟电路设计的专业工程师和技术人员,尤其是那些需要精确测量交流电信号均方根值的应用开发者。 使用场景及目标:①用于工业自动化、医疗设备、电力监控等领域,实现对交流电压或电流的精准测量;②适用于手持式数字万用表及其他便携式仪器仪表,提供高效的单电源解决方案;③在电流互感器配置中,用于检测微小的电流变化,保障电气安全;④应用于三相电力系统监控,优化建立时间和转换精度。 其他说明:为了确保最佳性能,文档推荐使用高质量的电容器件,并给出了详细的PCB布局指导。同时提醒用户关注电介质吸收和泄漏电流等因素对测量准确性的影响。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值