[Pku 2352 2155 Hdu 3584] 线段树(五) {树状数组}
2010-10-24 20:35
274 查看
{
就我学过的数据结构而言
最优美的数据结构是并查集
然后是树状数组
再次是散列表
......
}
优美的含义就是简明 精巧
当然特别强大的数据结构一般都不好写
比如Splay 线段树 平衡树之类
所以也不是很优美
线段树确实强大 但是在有些情况下
我们可以用树状数组实现线段树的一部分功能
通常意义上的树状数组是一个一维数组 我们一般用c[]来记录
相对的 还有一个原数组a[] 记录原有的序列 c[]是基于a[]而产生的
树状数组可以实现查询区间和和修改单值的操作
这些操作线段树也可以实现 理论复杂度同样为O(Log2N)
但是树状数组的常数和编程复杂度更低
对于可以转化为这两个操作的问题 我们优先考虑树状数组
而且树状数组还有比线段树更好的可扩展性 可以轻易地扩展到高维
只需把通常意义上的树状数组改造成N维的树状数组即可
显然N维的线段树是相当恐怖的东西 相比而言 N维的树状数组就优美了许多
要理解树状数组 看几张图即可
具体的算法可以到baidu去找 三个函数才几行话{Lowbit(),Getsum(),Change()}
各人的理解方式可能不同 自己理解出来的才是最好的
提示一下 树状数组的核心是二进制思想
相信大家小时候都做过这个这个问题 任何一个数可以拆成不同的2的幂的和
树状数组通俗的讲就是这个道理
由于拆出的数的个数不超过Log2N个 树状数组的复杂度就是O(Log2N)
树状数组的入门问题
Pku 2352 http://poj.org/problem?id=2352
算法也很简单
把所有星星都投影到x轴上
由于给的星星是有顺序的(从下到上 从左到右)
每次插入一个星星 就累加当前的统计值 最后输出即可
树状数组很优美 但是这优美不是轻易能领略的 需要进行转化
原本树状数组支持的操作是修改一个数 查询区间和
我们有时候会碰到查询一个数 修改区间值的问题
同样可以通过转化来用树状数组解决
对于查询一个数a[i]我们转化为getsum(i) 即把a[i]转化为长为i前缀和
而修改区间我们如下图操作
修改[x,y] 我们就change(x,1) change(y+1,-1)
不难发现 对[x,y]内的数getsum就会+1 否则是不变的 这就相当于区间修改了
树状数组可以轻易的扩展到2维 3维
看两个这样的问题
Pku 2155 http://poj.org/problem?id=2155
Hdu 3584 http://acm.hdu.edu.cn/showproblem.php?pid=3584
分别是树状数组的二维和三维延伸
题意差不多
给定0 1阵 支持取反一个区间 查询单个值
对于取反操作 我们记录取反的次数 然后取2的模就可以反映当前的值了
这样问题就是支持区间修改和查询单值的问题
如果是一维的问题直接使用上面所说的方法就可以解决
现在是二维 三维了
二维的树状数组只是加了一维 操作只是多了一重循环
具体的操作可以baidu而知 不再赘述
我们可以如下图对c[][]进行修改 然后getsum(i,j)来求当前a[i,j]的值
三维需要画一个好一点的图 画出来了很有成就感 试一试吧
代码很好懂 具体看代码
Matrix
Cube
BOB HAN 原创 转载请注明出处 http://www.cnblogs.com/Booble/
本文图片来自 http://hi.baidu.com/edelweisszf/blog/item/dd8a2fa2dfc60babcbefd013.html
(写的也很好 建议一起看)
就我学过的数据结构而言
最优美的数据结构是并查集
然后是树状数组
再次是散列表
......
}
优美的含义就是简明 精巧
当然特别强大的数据结构一般都不好写
比如Splay 线段树 平衡树之类
所以也不是很优美
线段树确实强大 但是在有些情况下
我们可以用树状数组实现线段树的一部分功能
通常意义上的树状数组是一个一维数组 我们一般用c[]来记录
相对的 还有一个原数组a[] 记录原有的序列 c[]是基于a[]而产生的
树状数组可以实现查询区间和和修改单值的操作
这些操作线段树也可以实现 理论复杂度同样为O(Log2N)
但是树状数组的常数和编程复杂度更低
对于可以转化为这两个操作的问题 我们优先考虑树状数组
而且树状数组还有比线段树更好的可扩展性 可以轻易地扩展到高维
只需把通常意义上的树状数组改造成N维的树状数组即可
显然N维的线段树是相当恐怖的东西 相比而言 N维的树状数组就优美了许多
要理解树状数组 看几张图即可
具体的算法可以到baidu去找 三个函数才几行话{Lowbit(),Getsum(),Change()}
各人的理解方式可能不同 自己理解出来的才是最好的
提示一下 树状数组的核心是二进制思想
相信大家小时候都做过这个这个问题 任何一个数可以拆成不同的2的幂的和
树状数组通俗的讲就是这个道理
由于拆出的数的个数不超过Log2N个 树状数组的复杂度就是O(Log2N)
树状数组的入门问题
Pku 2352 http://poj.org/problem?id=2352
算法也很简单
把所有星星都投影到x轴上
由于给的星星是有顺序的(从下到上 从左到右)
每次插入一个星星 就累加当前的统计值 最后输出即可
const maxn=15000; maxm=32001; var x,y:array[1..maxn]of longint; c:array[1..maxm]of longint; h:array[0..maxn-1]of longint; i,n,m:longint; function lowbit(v:longint):longint; begin lowbit:=v and -v; end; procedure insert(x:longint); var y:longint; begin y:=x; while y<=m do begin c[y]:=c[y]+1; y:=y+lowbit(y); end; end; function query(x:longint):longint; var ans,y:longint; begin y:=x; ans:=0; while y>0 do begin ans:=ans+c[y]; y:=y-lowbit(y); end; query:=ans; end; begin assign(input,'star.in'); reset(input); assign(output,'star.out'); rewrite(output); readln(n); m:=0; for i:=1 to n do begin readln(x[i],y[i]); if m<x[i] then m:=x[i]; end; m:=m+1; for i:=1 to n do begin inc(h[query(x[i]+1)]); insert(x[i]+1); end; for i:=0 to n-1 do writeln(h[i]); close(input); close(output); end.
树状数组很优美 但是这优美不是轻易能领略的 需要进行转化
原本树状数组支持的操作是修改一个数 查询区间和
我们有时候会碰到查询一个数 修改区间值的问题
同样可以通过转化来用树状数组解决
对于查询一个数a[i]我们转化为getsum(i) 即把a[i]转化为长为i前缀和
而修改区间我们如下图操作
修改[x,y] 我们就change(x,1) change(y+1,-1)
不难发现 对[x,y]内的数getsum就会+1 否则是不变的 这就相当于区间修改了
树状数组可以轻易的扩展到2维 3维
看两个这样的问题
Pku 2155 http://poj.org/problem?id=2155
Hdu 3584 http://acm.hdu.edu.cn/showproblem.php?pid=3584
分别是树状数组的二维和三维延伸
题意差不多
给定0 1阵 支持取反一个区间 查询单个值
对于取反操作 我们记录取反的次数 然后取2的模就可以反映当前的值了
这样问题就是支持区间修改和查询单值的问题
如果是一维的问题直接使用上面所说的方法就可以解决
现在是二维 三维了
二维的树状数组只是加了一维 操作只是多了一重循环
具体的操作可以baidu而知 不再赘述
我们可以如下图对c[][]进行修改 然后getsum(i,j)来求当前a[i,j]的值
三维需要画一个好一点的图 画出来了很有成就感 试一试吧
代码很好懂 具体看代码
Matrix
const maxn=1000; var c:array[1..maxn,1..maxn]of longint; i,x1,y1,x2,y2,z,n,m:longint; ch:char; function lowbit(x:longint):longint; begin lowbit:=x and -x; end; procedure chg(x,y,z:longint); var i,j:longint; begin i:=x; while i<=n do begin j:=y; while j<=n do begin c[i][j]:=c[i][j]+z; j:=j+lowbit(j); end; i:=i+lowbit(i); end; end; function gs(x,y:longint):longint; var ans,i,j:longint; begin ans:=0; i:=x; while i>0 do begin j:=y; while j>0 do begin ans:=ans+c[i][j]; j:=j-lowbit(j); end; i:=i-lowbit(i); end; gs:=ans; end; begin assign(input,'matrix.in'); reset(input); assign(output,'matrix.out'); rewrite(output); readln(z); while z<>0 do begin dec(z); readln(n,m); for i:=1 to m do begin read(ch); case ch of 'C': begin readln(x1,y1,x2,y2); chg(x1,y1,1); chg(x1,y2+1,-1); chg(x2+1,y1,-1); chg(x2+1,y2+1,1); end; 'Q': begin readln(x1,y1); writeln(gs(x1,y1)and 1); end; end; end; writeln; fillchar(c,sizeof(c),0); end; close(input); close(output); end.
Cube
const maxn=100; var i,n,m,ch,x1,x2,y1,y2,z1,z2:longint; c:array[1..maxn,1..maxn,1..maxn]of longint; function lowbit(x:longint):longint; begin lowbit:=x and -x; end; procedure chg(x,y,z,ch:longint); var i,j,k:longint; begin i:=x; while i<=n do begin j:=y; while j<=n do begin k:=z; while k<=n do begin c[i][j][k]:=c[i][j][k]+ch; k:=k+lowbit(k); end; j:=j+lowbit(j); end; i:=i+lowbit(i); end; end; function gs(x,y,z:longint):longint; var ans,i,j,k:longint; begin ans:=0; i:=x; while i>0 do begin j:=y; while j>0 do begin k:=z; while k>0 do begin ans:=ans+c[i][j][k]; k:=k-lowbit(k); end; j:=j-lowbit(j); end; i:=i-lowbit(i); end; gs:=ans; end; begin assign(input,'cube.in'); reset(input); assign(output,'cube.out'); rewrite(output); while not eof do begin readln(n,m); for i:=1 to m do begin read(ch); case ch of 0: begin readln(x1,y1,z1); writeln(gs(x1,y1,z1)and 1); end; 1: begin readln(x1,y1,z1,x2,y2,z2); chg(x1,y1,z1,1); chg(x1,y2+1,z1,-1); chg(x2+1,y1,z1,-1); chg(x2+1,y2+1,z1,1); chg(x1,y1,z2+1,-1); chg(x1,y2+1,z2+1,1); chg(x2+1,y1,z2+1,1); chg(x2+1,y2+1,z2+1,-1); end; end; end; fillchar(c,sizeof(c),0); end; close(input); close(output); end.
BOB HAN 原创 转载请注明出处 http://www.cnblogs.com/Booble/
本文图片来自 http://hi.baidu.com/edelweisszf/blog/item/dd8a2fa2dfc60babcbefd013.html
(写的也很好 建议一起看)
相关文章推荐
- poj 2155 Matrix(二维树状数组) hdu 3584 Cube(三维)
- hdu 1541 Stars poj 1195 Mobile phones(二维) poj 2155 Matrix(二维) hdu 3584 Cube(三维) 树状数组
- POJ-2155 Matrix 二维树状数组, HDU-3584 Cube 三维树状数组
- poj 2352 hdu 2642 hdu 1556 poj 2155 树状数组
- pku2352 线段树
- hdu 1166 敌兵布阵 (线段树、树状数组模板,单点更新)
- HDU 4217 Data Structure?(线段树 or 树状数组啊)
- HDU 1166 敌兵布阵 (线段树 & 树状数组)
- HDU ~ 1394 ~ Minimum Inversion Number(暴力||归并排序||线段树||树状数组)
- HDU 3333 Turing Tree 线段树 or 树状数组
- HDU~1556 Color the ball(线段树区间更新||树状数组)
- HDU 1754 I Hate It (线段树 & 树状数组)
- HDU 3584 Cube --三维树状数组
- HDU 1166 敌兵布阵(区间求和&(线段树|树状数组))
- HDU - 3584 Cube(三维树状数组)
- HDU-2795 Billboard 线段树|树状数组
- hdu 3584 Cube(三维树状数组)
- HDU 4970 Killing Monsters 线段树 || 树状数组
- HDU 4046 Panda(RMQ 线段树 树状数组)
- HDU 3584 Cube(三维树状数组)