码迷,mamicode.com
首页 > 其他好文 > 详细

点分治基础应用

时间:2018-09-25 21:55:17      阅读:170      评论:0      收藏:0      [点我收藏+]

标签:cal   节点   math   点分治   span   动态   统计   get   关键字   

概述

点分树代表了树上的所有路径,如同分治代表了序列中的所有区间。在点分树节点上统计经过这个点的树链的答案。

int calcn, grasiz, gra;
void getgra(int u, int pa) { // 找当前联通块重心
    siz[u] = 1; int maxsiz = 0;
    for(int i = 0; i < G[u].size(); i++) {
        int v = G[u][i];
        if(v == pa || graed[v]) continue;
        getgra(v, u);
        siz[u] += siz[v];
        maxsiz = max(maxsiz, siz[v]);
    }
    maxsiz = max(maxsiz, cn-siz[u]);
    if(maxsiz < grasiz) {
        grasiz = maxsiz;
        gra = u;
    }
}

struct dt_ {
    int fa[maxn];
    void build(int u, int pa) {
        fa[u] = pa; // 点分树结构 
        graed[u] = 1;
        int cn = calcn; // 这个点分树节点对应的联通块大小
        for(int i = 0; i < G[u].size(); i++) {
            int v = G[u][i];
            if(graed[v]) continue;
            grasiz = inf;
            if(siz[v] > siz[u]) calcn = cn - siz[u]; //是原树上的父亲
            else calcn = siz[v];
            getgra(v, u);
            build(gra, u);
        }
    }
}dt;


int main() {
    //...
    calcn = n; grasiz = inf; // calcn 计算重心的联通块大小
    getgra(0, -1);
    dt.build(0, -1);
    //...
}

距离k联通块修改/询问

此类问题的做法是通用的。

对每个点分树结点开两棵动态开点线段树,一棵记录以结点到自己的距离为关键字的结点信息,另一棵记录以结点到点分树父亲的距离为关键字的结点信息。

由点分树性质,点分树最大深度为\(\log n\)。因此修改、询问时从下往上从节点到点分树根做即可。询问时需要减去结点先到点分树父亲再到当前点分树结点的贡献。总复杂度为\(O(n\log^2n)\)

例题:震波,烁烁的游戏。

树链统计

统计经过每个点分树节点的答案。

结论

点分树可以统计对长度有要求的树链、联通块问题。

点分治基础应用

标签:cal   节点   math   点分治   span   动态   统计   get   关键字   

原文地址:https://www.cnblogs.com/utopia999/p/9703589.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!