CF600E Lomsat gelral(DSU on tree)

题面
先考虑O(n2)O(n^2)暴力,DFSDFS到每个点之后再暴力统计它的子树答案即可
仔细观察,我们发现一个点没有好好利用它儿子的贡献.可以发现,每个点最后遍历到的一棵子树贡献可以被保留,这样计算该节点答案的时候就可以少遍历最后一棵子树,直接利用最后一棵子树的贡献.显然把最大的子树留到最后遍历最优,可以证明这样做是O(nlogn)O(nlogn)的(然而我并不会证)

void dfs(LL now,LL fa,LL keep=0){//keep=1则保留贡献
    out(i,v,now)
    if (to!=fa && to!=son[now]){
        dfs(to,now);//遍历其它子树
    }
    if (son[now]) dfs(son[now],now,1);//遍历最大的子树
    inc(col[now]);
    out(i,v,now) if (to!=fa && to!=son[now]) xg(to,now,1);//统计答案
    ans[now]=cnt[ma];
    if (!keep){
        dec(col[now]);
        out(i,v,now) if (to!=fa) xg(to,now,-1);
    }
}

Code

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章