对于某些对子树的统计问题,我们固然可以用DSU on Tree来解决,但是一旦带上修改,甚至是加上历史化版本的查询,我们就不得不求助于其他的算法,本篇将对线段树合并进行讲解
线段树合并一般用于对子树的统计,一般的套路就是对树的每一个节点都开上一颗动态开点线段树,然后统计子树信息时,合并所有儿子信息,统计答案,然后继续向上走;
例题也很多,比如[USACO17JAN]Promotion Counting晋升者计数,【NOIP2016 DAY1】天天爱跑步等等都可以这样乱搞,实现起来也非常好理解,这是针对天天爱跑步类型(权值线段树)的\(Merge\)代码:
\(code\):
void merge(int &x,int y)
{
if(!x||!y){x=x+y;return;}
sum[x]+=sum[y];
merge(ls[x],ls[y]);
merge(rs[x],rs[y]);
}
如果希望改为维护历史版本,可以这样改:
int merge(int x,int y)
{
if(!x||!y){ return x+y;return;}
int p=++tot;
ls[p]=merge(ls[x],ls[y]);
rs[p]=merge(rs[x],rs[y]);
sum[p]=sum[ls[p]]+sum[rs[p]]
return p;
}
简单好写,易于理解
原文地址:https://www.cnblogs.com/KatouKatou/p/9859459.html
时间: 2024-08-01 06:56:04