树状数组题目小结 - 入门篇(模板题)
A. POJ-2352
B. POJ-3067
C. luogu-3368-树状数组 2
D. hdu-1166-敌兵布阵
E. hdu-1556-Color the ball
F. POJ-3468
G. POJ-2481
H. POJ -2299
I. POJ -1990
J. POJ-2155
K. POJ-3321
A. POJ-2352
点修改 + 区间和
/*
nero
2019-8-20 20:39:45
1A
*/
#include
B. POJ-3067
点修改+区间和
/*
nero
2019-8-20 17:40
long long WA1
*/
#include
C. luogu-3368-树状数组 2
区间加+点查询
/*
nero
*/
#include
D. hdu-1166-敌兵布阵
单点修改+区间和
前两天做线段树刚刚做过,又遇到了。
#include
E. hdu-1556-Color the ball
区间加 + 单点查询
/*
nero
2019-8-17 11:07:15
*/
#include
F. POJ-3468
区间加 + 区间和
/*
nero
2019-8-23 20:43:49
*/
#include
G. POJ-2481
           \;\;\;\;\; 区间覆盖,点修改+区间和
           \;\;\;\;\; 按照左端点由小到大排序,每次只要看前面有多少右端点比当前的右端点大,最后更新右端点的值。
           \;\;\;\;\; 有个需要注意的地方就是,两个区间可能会重合。这个时候就不能算。
           \;\;\;\;\; 这个题有点玄学,按照我的写法,行末不输出多余的空格,在G++里面会T,C++可过。换种写法也可过。听学长说一般不用注意这个点。
/*
nero
2019-8-23 21:21:30
*/
#include
H. POJ -2299
           \;\;\;\;\; 点修改+区间和
           \;\;\;\;\; 求逆序对,离散化,去重用了 unique 函数
/*
nero
2019-8-17 10:18:08
*/
#include
I. POJ -1990
           \;\;\;\;\; 点修改+区间和
           \;\;\;\;\; 这个题需要推一下。
           \;\;\;\;\; a n s = ∑ i = 1 n ∑ j = 1 i − 1 m a x ( v i , v j ) ⋅ ∣ x i − x j ∣ ans = \sum_{i=1}^{n}\sum_{j=1}^{i-1}max(v_{i}, v_{j}) \cdot |x_{i} - x_{j}| ans=∑i=1n∑j=1i−1max(vi,vj)⋅∣xi−xj∣, 答案里面有两个因素,一个是阈值,一个是距离。某一个元素 ( v i , x i ) (v_{i}, x_{i}) (vi,xi) 对于答案的贡献有多少,要看其它元素 v j v_{j} vj 和 v i v_{i} vi 的大小关系。只要对于每个元素,求出它关于那些 v j < v i v_{j} < v_{i} vj<vi 的元素的贡献就好。比它大的会在大的那里求。
           \;\;\;\;\; 对于所有 v j < v i v_{j} < v_{i} vj<vi 的元素,答案就是 ∑ v i ⋅ ∣ x i − x j ∣ \sum v_{i} \cdot |x_{i} - x_{j}| ∑vi⋅∣xi−xj∣,其中 v i v_{i} vi 可以提取出来,这样就是求 ∑ ∣ x i − x j ∣ \sum |x_{i} - x_{j}| ∑∣xi−xj∣;
           \;\;\;\;\; 对于 x i > x j x_{i} > x_{j} xi>xj 的元素, ∑ ∣ x i − x j ∣ = ∑ x i − ∑ x j = c n t 1 ⋅ x i − ∑ x j \sum |x_{i} - x_{j}| = \sum x_{i} - \sum x_{j} = cnt1 \cdot x_{i} - \sum x_{j} ∑∣xi−xj∣=∑xi−∑xj=cnt1⋅xi−∑xj,其中 c n t 1 cnt1 cnt1 为 x i > x j x_{i} > x_{j} xi>xj 的数量;
           \;\;\;\;\; 对于 x i < x j x_{i} < x_{j} xi<xj 的元素, ∑ ∣ x i − x j ∣ = ∑ x j − ∑ x i = ∑ x j − c n t 2 ⋅ x i \sum |x_{i} - x_{j}| = \sum x_{j} - \sum x_{i} = \sum x_{j} - cnt2 \cdot x_{i} ∑∣xi−xj∣=∑xj−∑xi=∑xj−cnt2⋅xi,其中 c n t 2 cnt2 cnt2 为 x i < x j x_{i} < x_{j} xi<xj 的数量;
           \;\;\;\;\; 用树状数组维护每个 x i x_{i} xi 的 数量 以及 前缀和 就好。
/*
nero
2019-8-26 10:27:12
long long 用了 %d WA1
*/
#include
J. POJ-2155
           \;\;\;\;\; 操作1:在一个矩阵里面,元素有两种状态,每次改变一个矩形内的元素的状态。
           \;\;\;\;\; 操作2:查询某点状态。
           \;\;\;\;\; 简单的二维树状数组
           \;\;\;\;\; 区间加+单点查询
/*
nero
2019-8-20 16:49:18
数组清空 WA1
格式错误 WA1
*/
#include
K. POJ-3321
           \;\;\;\;\; dfs+单点修改+区间和
           \;\;\;\;\; 一开始想的是,每dfs一下,每次改变状态的时候只要更新其父节点即可。T了一发后才想到,一条链岂不是。。。
           \;\;\;\;\; 用 dfs 给点重新编号,寻找一个点的子树中编号最小和最大的点,就得到了这个点的左右区间,(感觉有点像多叉的线段树),问某个子树的苹果数量就变成了求区间和。
           \;\;\;\;\; 这个题卡vector,改成数组之后就过了,不过评论里面说,用 vector < vector >int 也可过。(连续两天连续卡两个题真的很难受)
/*
nero
2019-8-23 23:47:37
dfs 会 T, 只有一条链
vector 会 T,用数组
*/
#include
题目参考:【140508专题】树状数组——题目集