欢迎使用本站,预祝练习时长两年半的选手们到成功! [本模块信息来自tem/def/head]

class120-121 树链剖分01 zxy

时间:2024-07-24 12:21 作者:admin 点击:
HLD 树链剖分 应用于树形数据结构上进行优化的查询和更新操作 快速查询或修改,O(logn) 可能求的:最大、最小、和、路径更新 重(zhong)节点:每个链都是从某节点开始到子树中的一

HLD 树链剖分

应用于树形数据结构上进行优化的查询和更新操作

快速查询或修改,O(logn)

可能求的:最大、最小、和、路径更新

重(zhong)节点:每个链都是从某节点开始到子树中的一个重节点的路径。

'轻''重'实际上是用来形容【边】的,不是节点。

如果一条边记录为重,那么才能进行相连。

如果只有一个点,那它本身也是一条链。


进行树链剖分:

   1、构建链:遍历树结构,为各个边标记"重"或"轻"。通过DFS完成,每个节点至多有一条重链,可以有多条轻链。

   2、预处理:为了加速查询或修改,需要使用线段树等手段对每个链进行预处理,这样单次的查询或修改时间复杂度就是O(logn)

   3、执行查询、更新操作。




前提是要先存好一棵树

1、dfshld() 分出轻重

2、dfspos() 节点定位


//结构体建链

struct edge{

   int to;

   int next;

   int weight=1;

};

struct node{

   int depth;

   int heavy;//重量

   int heavychild;

   int listid;//记录存放的重链id

   vector<edge> es;

} nodes[MAXN];

int N;

void addEdge(int u,int v,int w=1){

   nodes[u].es.push_back({v,nodes[u].es.size(),w});

   nodes[v].es.push_back({u,nodes[v].es.size(),w});

}

int main(){

   cin>>N>>R;

   for(int i=1;i<N;i++){

       int u,v,w;//

       cin>>u>>v;

       addEdge(u,v);

   }

   dfsHLD1(R,0);//从根节点开始,求重量

   dfsHLD2(R);//从根节点开始,找重链

   通过listed遍历各个链

}

int dfsHLD1(int root,int depth){

   nodes[root].depth=depth;

   int maxhe=0;

   nodes[root].heavy=1;

   for(auto &e:nodes[root].es){

       int child=e.to;

       nodes[root].heavy+=dfsHLD(child,depth+1);

   }

}

int listid=1;

void dfsHLD2(int root){

   nodes[root].listid=listid++;

   nodes[root].heavychild=0;

   int k=0;

   for(auto &e:nodes[root].es){

       int child=e.to;

       if(k<nodes[child].heavy){

           k=nodes[child].heavy;

           nodes[root].heavychild=child;

       }

   }

   for(auto &e:nodes[root].es){

       int child=e.to;

       if(child!=nodes[root].heavychild)

           dfsHLD2(child);

   }

}

(责任编辑:admin)
    顶一下
    (0)
    0%
    踩一下
    (0)
    0%