【JZOJ 3397】 雨天的尾巴

Description

一棵树,有若干操作,每个操作包含三个数x,y,z,表示在树上从x到y的路径上的所有点的z颜色的权值+1。所有操作结束后询问每个点权值最大的颜色是什么。

对于100% 的数据,1 <= n,m <= 100000; 1 <= x, y <= n; 1 <= z <= 10^9

Analysis

这道题是用的线段覆盖的思想。只不过放在树上。
我们想树上的两个点u,v之间的路径可以由(root,u)+(root,v)-(root,lca(u,v))-(root,fa(lca(u,v)))构成。
所以线段覆盖放在树上可以转化成每个点信息的合并。即从下往上做,每个点的信息与其所有子节点合并。
在这里,显然每个点的信息就是颜色权值了。
怎么记录?权值线段树!空间会爆?首先把操作的z离散化,然后动态开节点!
然后就是线段树的操作了。
由于本人弱,这是第一道线段树合并的题。
两棵线段树合并,对应的节点搜下来,若一个为空就返回另一个,否则合并节点的左右子节点。合并到叶子节点就将权值直接“+”一下(这个+指满足结合律的所有运算)

Key Code

我自己原始的code太恶心,于是观摩了一下alan_cty的,果然大神就是大神,代码简洁明了又实用%%%

int merge(int x,int y,int l,int r)
{
    if(!x || !y) return x+y;
    if(l==r)
    {
        a[x].mx+=a[y].mx;
        return x;
    }
    int mid=(l+r)>>1;
    a[x].l=merge(a[x].l,a[y].l,l,mid);
    a[x].r=merge(a[x].r,a[y].r,mid+1,r);
    a[x].mx=max(a[a[x].l].mx,a[a[x].r].mx);
    return x;
}

你可能感兴趣的:(线段树,离散化,权值线段树,线段树合并)