参考
本博文又名:手把手教你写树状数组
1. 单点修改,子树和查询
单点修改,区间查询
树状数组
维护每个点的权值:
1. 修改
x
(增加add(x,w);
2. 查询
x
的子树:区间查询——ans=query(le[x])-query(ri[x]-1);
2. 单点修改,树链和查询
首先将
考虑修改点
x
,影响到的即为
至于查询,则是四个单点查询。
线段树
维护每个节点到
root
的权值和:
1. 修改
x
(增加modify(1,le[x],ri[x],w);
2. 查询
[u,v]
链:单点查询——查询
u,v,lca(u,v),fa(lca(u,v))
,
ans=query(1,u)+query(1,v)-query(1,lca(u,v))-query(1,fa(lca(u,v)));
(本质上即四次查询
x
:query(1, x);
)
树状数组
前缀和维护点到
1. 修改
x
(增加add(le[x],w),add(ri[x]+1,-w);
2. 查询
[u,v]
链:单点查询——ans=[u,v]间权值和的初始值+query(le[u])+query(le[v])-query(le[lca(u,v)])-query(le[fa(lca(u,v))]);
(本质上即四次查询
x
:query(x);
)
3. 树链修改,单点查询
树链修改的道理同上,等价于修改某个点到
考虑修改的树链的一个端点为
x
,增加值为
对于点
树状数组
维护每个点权值的变化量:
1. 修改
[u,v]
链(增加
w
):单点修改——add(u,w),add(v,w),add(lca(u,v),-w),add(fa(lca(u,v)),-w);
(本质上即四次修改add(x,w);
)
2. 查询
x
:区间查询——ans=x的初始值+query(ri[x])-query(le[x]-1);
4. 树链修改,子树和查询
树链修改的道理同上,等价于修改某个点到
考虑修改的树链的一个端点为
x
,影响到的则是
y
的变化量总和则为
仍是单点修改,区间查询
树状数组
开两个树状数组,分别维护
w[x]∗(depth[x]+1)
与
w[x]
.
1. 修改
[u,v]
链(增加
w
):单点修改——
add1(u,w*(depth[u]+1)),add1(v,w*(depth[v]+1)),add1(lca(u,v),-w*(depth[lca(u,v)]+1)),add1(fa(lca(u,v)),-w*(depth[fa(lca(u,v)]+1);
add2(u,w),add2(v,w),add2(lca(u,v),-w),add2(fa(lca(u,v)),-w);
(本质上即八次修改add(x,w);
)
2. 查询
x
的子树:区间查询——
ans=子树和的初始值+query1(ri[x])-query1(le[x]-1)-depth[x]*(query2(ri[x])-query2(le[x]-1));
5. 子树修改,单点查询
区间修改,单点查询
树状数组
前缀和维护点权值的变化量:
1. 修改add(le[x],w),add(ri[x]+1,-w);
2. 查询ans=x的初始值+query(le[x]);
6. 子树修改,子树和查询
区间修改,区间查询
线段树
维护每个点的权值
1. 修改
x
的子树(增加add(1,le[x],ri[x],w);
2. 查询
x
的子树:区间查询——ans=query(1,le[x],ri[x]);
树状数组
具体见【小结】树状数组的区间修改与区间查询 ——MoeO3,本菜就不多废话了_(:3」∠)_
(已经赤果果地变成一篇树状数组的文章啦(逃
7. 子树修改,树链和查询
树链修改的道理同2. 3. 4. ,等价于修改某个点到
考虑修改
x
的子树,影响的则是
树状数组
开两个树状数组,分别维护
w[x]∗(−depth[x]+1)
与
w[x]
.
1. 修改
x
的子树(增加
add1(le[x],w[x]*(-depth[x]+1);add1(ri[x]+1,-w[x]*(-depth[x]+1);
add2(le[x],w[x]);add2(ri[x]+1,-w[x]);
2. 查询
[u,v]
链:单点查询——
ans=[u,v]间权值和的初始值+(query1(le[u])+query1(le[v])-query1(le[lca(u,v)])-query1(le[fa(lca(u,v))]))+depth[y]*(query2(le[u])+query2(le[v])-query2(le[lca(u,v)])-query2(le[fa(lca(u,v))]));
(本质上即八次查询
x
:query(x)
)
完结撒花~
哪里有错误还烦请批评指正啦