数据结构:树状数组

  关于树状数组的概述,可以看一下这篇博客:http://blog.csdn.net/int64ago/article/details/7429868

  树状数组是一个可以高效地进行区间统计的数据结构,在思想上类似于线段树,比线段树节省空间,编程复杂度比线段树低,但适用范围比线段树小。主要工作也是查询和更新。

  例题:POJ - 2352    (http://poj.org/problem?id=2352

  题目大意:输入n个星星坐标,坐标按y递增顺序输入,y相同按x递增顺序输入。定义一个星星的级别是横纵坐标都不超过自己的星星个数(不包括自己),问级别为0~n-1的星星分别有多少个。

  题目思路:我们可以发现,当前输入这个星星,跟后面的星星没有关系,因为后面输入的星星横纵坐标肯定会有超过当前星星的。所以只要把当前输入的x之前的横坐标加起来就可以了。树状数组非常非常的符合这个特性。要注意的一点是树状数组下标从1开始算,所以把题目输入的横坐标全部右移了一位。

  代码:  http://paste.ubuntu.com/16317880/

 1 #include <iostream>
 2 using namespace std;
 3 int tree[32001],level[32001];
 4 int lowbit(int x){return x&(-x);}
 5 int read(int k)
 6 {
 7     int sum=0;
 8     while(k)
 9     {
10         sum += tree[k];
11         k -= lowbit(k);
12     }
13     return sum;
14 }
15 void add(int k)
16 {
17     while(k<=32001)
18     {
19         tree[k]++;
20         k += lowbit(k);
21     }
22 }
23 int main()
24 {
25     int n,i,x,y;
26     cin>>n;
27     for(i=0;i<n;i++)
28     {
29         cin>>x>>y;
30         level[read(x+1)]++;        //全部x右移一位
31         add(x+1);
32     }
33     for(i=0;i<n;i++)
34         cout<<level[i]<<endl;
35 }
时间: 2024-10-13 21:05:20

数据结构:树状数组的相关文章

数据结构——树状数组

我们今天来讲一个应用比较广泛的数据结构——树状数组 它可以在O(nlogn)的复杂度下进行单点修改区间查询,下面我会分成三个模块对树状数组进行详细的解说,分别是树状数组基本操作.树状数组区间修改单点查询的实现.树状数组查询最值的实现 一. 树状数组一般分为三种操作,初始化.修改.查询 在讲基本操作之前,我们先来看一张图 这张图就是树状数组的存储方式,对于没有接触过树状数组的人来说看懂上面这张图可能有些困难,上图的A数组就是我们的原数组,C数组则是我们需要维护的数组,这样存储能干什么呢,比如我们在

HDU 1556 数据结构-树状数组-改段求点

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1556 解题思路:树状数组,只要了解树状数组的原理就不用死记模板了,总之树状数组管理的就是前缀和,高度越高的的结点管理的范围越广 所以要是改点求段:更改一个点就要向上传递 所以要是改段求点:更改一个点就要向下传递 代码: #include <cstdio> #include <iostream> #include <cstring> using namespace std;

数据结构——树状数组篇

原地址:My CSDN Blog  那边还未通过审核,先看这边的吧…… 线段树是一个很好的维护区间关系的这样的一个数据结构,但是,很多时候我们可以用更小空间.更快速度(更大尺寸呢.,全景天窗,五菱宏光?)的数据结构来维护一个前缀关系. ??? 上面的这张图是表示的一个有8个叶子节点的线段树,接下去,我们给它进行一个变形: ??? 然后呢,我们把2.4.6.8.……这样的元素推到最顶端的空上边去,想让2表示1-2这段区间,让4表示1-4这段区间,让6表示5-6这段区间,让8表示1-8这段区间. 然

实用数据结构---树状数组(二叉索引树)

树状数组适用于动态连续和查询问题,就是给定一个区间, 查询某一段的和或者修改某一位置的值. 关于树状数组的结构请去百度百科,否则将看不懂下面内容 我们看这个题 士兵杀敌(二) 时间限制:1000 ms  |  内存限制:65535 KB 难度:5 描述 南将军手下有N个士兵,分别编号1到N,这些士兵的杀敌数都是已知的. 小工是南将军手下的军师,南将军经常想知道第m号到第n号士兵的总杀敌数,请你帮助小工来回答南将军吧. 南将军的某次询问之后士兵i可能又杀敌q人,之后南将军再询问的时候,需要考虑到新

用树状数组处理逆序对[数据结构][树状数组]

逆序对 ——!x^n+y^n=z^n 可以到这里[luogu]: https://www.luogu.org/problem/show?pid=1908 题意:对于给定的一段正整数序列,逆序对就是序列中ai>aj且i<j的有序对.知道这概念后,他们就比赛谁先算出给定的一段正整数序列中逆序对的数目. 假如为这些数为: 8 2 3 1 7 如果我们把数一个个加进来,用一个数组a[i]统计i出现了几次. a的初始状态: 8加进来后: 由于不存在比8大的数,说明没有产生逆序对 2加进来后: 统计比2大

ACM数据结构-树状数组

模板: int n; int tree[LEN]; int lowbit(int x){ return x&-x; } void update(int i,int d){//index,delta while(i<=n){ tree[i]+=d; i+=lowbit(i); } } int getsum(int i){ int ans=0; while(i>0){ ans+=tree[i]; i-=lowbit(i); } return ans; } 示意图: 1.Ultra-Quic

[数据结构] 树状数组 的C程序实现

int tree[100001];//树状数组,用于取区间[x,y]的数据的和 /* & 特殊运算,t&(-t)的值(十进制),就是t在2进制下,从右往左数第一个1出现的位置. 结合树状数组的特殊性质,这个值有用 */ int lowbit(int t) { return t&(-t); } /* 假设对处在数组序号x的数据进行了更改,让x位置的数据有了增量v 对树状数组进行如下修改,使相关的包含x位数据的和都增加v 根据树状数组的性质,也就是对下标为 x, x+lowbit(x)

2019.9.25 初级数据结构——树状数组

一.树状数组基础 学OI的同学都知道,位运算(对二进制的运算)比普通运算快很多.同时我们接触到了状态压缩的思想(即将0-1的很多个状态压缩成十进制的一个数,每一个二进制位表示一个状态).由于在实际做题过程当中,由于数据范围限制,我们必须采用更高效的存储.查询方法,于是树状数组应运而生. 首先我们检查传统的存储状态.对于数组的每一个下标i,其所存储的有效信息只有一个a[i](这是传统数组).而对于树状数组,我们每一位下标可以存储lowbit(i)个有效信息.这个lowbit运算一会再说.所以尽管树

C++-hdu1166-敌兵布阵[数据结构][树状数组]

单点修改+区间查询=树状数组 空间复杂度O(n) 时间复杂度O(mlogn) 1 #include <set> 2 #include <map> 3 #include <cmath> 4 #include <queue> 5 #include <vector> 6 #include <cstdio> 7 #include <cstdlib> 8 #include <cstring> 9 #include <

C++-hdu1394-Minimum Inversion Number[数据结构][树状数组]

给出0~n-1的一个排列,可以整体移动,求逆序对最小值 把数字num[i]的加入,等价于树状数组的第n-num[i]位加1 因为num[i]是第 (n-1)-num[i]+1=n-num[i]大的数字,产生逆序对,只可能在其之前已经插入了数字,此时直接区间查询即可 1 #include <set> 2 #include <map> 3 #include <cmath> 4 #include <queue> 5 #include <vector>