Poj 树状数组

树状数组查询和修改复杂度都为log(n),假设数组a[1..n],那么查询a[1]+...+a[n]的时间是log(n),而且是一个在线的数据结构,

随时修改某个元素的值,复杂度也为log(n)。

 

 

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

 

Ci是其后2^k个数字的和,k= i & ( -i ),是将 i 写成二进制后末尾零的个数。

 

 

做了一些题总结树状数组有这么几种应用。

 

1.修改一个区域,查询一个点。

 

2.修改一个点,查询一个区域。

 

3.修改一个区域,查询一个区域。

 

 

 

poj 2352

一维树状数组,计算一个点左下的点有多少个。y是升序的。

 

 

 

poj3321

一维树状数组,此题树状数组倒是好写,关键是怎么用树状数组解。

我的做法是先深搜一次,重新给每个节点编号,利用节点新的编号来做树状数组。

 

 

 

poj 1656

二维树状数组,修改一个区域,查询一个区域

由于格子很小,只有100*100,所以修改的时候就直接两个for循环,查询的时候利用了它和的性质。

 

 

 

poj 1195

二维树状数组,修改一个点的值,查询一个区域的和。

修改点[x1,y1],查询时利用容斥原理则可得ans=(Sum(x2+1,y2+1)+Sum(x1,y1)-Sum(x2+1,y1)-Sum(x1,y2+1))).

 

 

 

poj 2155

二维树状数组,修改一个区域的值,查询一个点的值。

修改区域[x1,y1]到[x2,y2],根据树状数组将[x1,y1]增加1,则以其为顶点的右下的所有值都增加了1

利用容斥原理,将[x1,y2+1],[x2+1,y1]再翻转一次,[x2+1,y2+1]翻转一次即可。

查询的时候只需要查询[x1,y1]这个点。

 

 

 

hdoj 3584

三维树状数组,修改一个长方体空间的状态,查询空间中某点的状态,和二维的相同,利用三阶的容斥原理。

 

 

 

代码贴到后面的文章吧

POJ 2182是一道使用树状数组解决的题目,题目要求对给定的n个数进行排序,并且输出每个数在排序后的相对位置。树状数组是一种用来高效处理前缀和问题的数据结构。 根据引用中的描述,我们可以通过遍历数组a,对于每个元素a[i],可以使用二分查找找到a到a[i-1]中小于a[i]的数的个数。这个个数就是它在排序后的相对位置。 代码中的query函数用来求前缀和,add函数用来更新树状数组。在主函数中,我们从后往前遍历数组a,通过二分查找找到每个元素在排序后的相对位置,并将结果存入ans数组中。 最后,我们按顺序输出ans数组的元素即可得到排序后的相对位置。 参考代码如下: ```C++ #include <iostream> #include <cstdio> using namespace std; int n, a += y; } } int main() { scanf("%d", &n); f = 1; for (int i = 2; i <= n; i++) { scanf("%d", &a[i]); f[i = i & -i; } for (int i = n; i >= 1; i--) { int l = 1, r = n; while (l <= r) { int mid = (l + r) / 2; int k = query(mid - 1); if (a[i > k) { l = mid + 1; } else if (a[i < k) { r = mid - 1; } else { while (b[mid]) { mid++; } ans[i = mid; b[mid = true; add(mid, -1); break; } } } for (int i = 1; i <= n; i++) { printf("%d\n", ans[i]); } return 0; } ``` 这段代码使用了树状数组来完成题目要求的排序功能,其中query函数用来求前缀和,add函数用来更新树状数组。在主函数中,我们从后往前遍历数组a,通过二分查找找到每个元素在排序后的相对位置,并将结果存入ans数组中。最后,我们按顺序输出ans数组的元素即可得到排序后的相对位置。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [poj2182Lost Cows——树状数组快速查找](https://blog.youkuaiyun.com/aodan5477/article/details/102045839)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [poj_2182 线段树/树状数组](https://blog.youkuaiyun.com/weixin_34138139/article/details/86389799)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值