当前位置: 首页 > news >正文

树上启发式合并 学习记录

算法讲解163【挺难】树上启发式合并的原理和相关题目_哔哩哔哩_bilibili

适用于统计一个树中多个子树的信息的题目

适用于没有修改操作的题目

原理: 

对于每个轻儿子的子树先遍历统计他的答案, 再消除这个子树的影响, 然后遍历重儿子, 统计答案, 再遍历一遍轻儿子统计答案

因为对于每个点, 他会被再遍历一次, 那么他所处的集合就会倍增一次, 所以他被遍历的次数不超过log(n),  总体复杂度O(nlogn)

题目

U41492 树上数颜色 - 洛谷

#include<bits/stdc++.h>
using namespace std;
using i64 = long long;
// 不能使用0下标
// 传n + 1 使用下标 1~n
struct HLD {HLD(const int &n) : n(n), edge(n) {fa = dep = son = sz = top = dfn = out = rnk = std::vector<int>(n);}void addEdge(const int &x, const int &y) {edge[x].push_back(y);edge[y].push_back(x);}void dfs1(int u, int p) {sz[u] = 1;fa[u] = p;dep[u] = dep[p] + 1;for(const auto &v : edge[u]) {if(v == fa[u]) continue;dfs1(v, u);sz[u] += sz[v];if(sz[son[u]] < sz[v]) {son[u] = v;}}}void dfs2(int u, int t, int &dfncnt) {dfncnt++;dfn[u] = dfncnt;rnk[dfncnt] = u;top[u] = t;if(son[u] == 0) return;dfs2(son[u], t, dfncnt);for(const auto &v : edge[u]) {if(v == fa[u] || v == son[u]) continue;dfs2(v, v, dfncnt);}}void work(int root = 1) {int dfncnt = 0;dfs1(root, 0);dfs2(root, root, dfncnt);}int lca(int u, int v) {while(top[u] != top[v]) {if(dep[top[u]] < dep[top[v]]) {std::swap(u, v);}u = fa[top[u]];}return (dep[u] < dep[v] ? u : v);}int dis(int x, int y) {return dep[x] + dep[y] - 2 * dep[lca(x, y)];}// int kth(int id, int k) {//  if(k > dep[id]) return 0;//  while(dep[id] - dep[top[id]] + 1 <= k) {//      k -= (dep[id] - dep[top[id]] + 1);//      id = fa[top[id]];//  }//  return rnk[dfn[id] - k];// }vector<vector<int>> edge;vector<int> fa, dep, son, sz, top, dfn, out, rnk;int n;
};void solve() {int n;cin >> n;HLD tree(n + 1);vector<vector<int>> edge(n + 1);for (int i = 1; i < n; i++) {int u, v;cin >> u >> v;edge[u].push_back(v);edge[v].push_back(u);tree.addEdge(u, v);}vector<int> a(n + 1);for (int i = 1; i <= n; i++) cin >> a[i];vector<int> cnt(n + 1);int dif = 0;vector<int> ans(n + 1);tree.work(1);auto &dfn = tree.dfn;auto &rnk = tree.rnk;auto &son = tree.son;auto &sz = tree.sz;auto dfs = [&] (auto self, int u, int p, int keep) -> void {for (auto v : edge[u]) {if (v == p || v == son[u]) continue;self(self, v, u, 0);}if (son[u]) self(self, son[u], u, 1);cnt[a[u]]++;if (cnt[a[u]] == 1) dif++;for (auto v : edge[u]) {if (v == p || v == son[u]) continue;for (int i = dfn[v]; i <= dfn[v] + sz[v] - 1; i++) {cnt[a[rnk[i]]]++;if (cnt[a[rnk[i]]] == 1) dif++;}}ans[u] = dif;if (!keep) {dif = 0;for (int i = dfn[u]; i <= dfn[u] + sz[u] - 1; i++) {cnt[a[rnk[i]]]--;}}};dfs(dfs, 1, 0, 1);int m;cin >> m;while(m--) {int x;cin >> x;cout << ans[x] << '\n';}}int main() {std::ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);int T = 1;//cin >> T;while (T--) solve();return 0;
}

http://www.dtcms.com/a/454422.html

相关文章:

  • MCP 的核心概念和例子
  • 淘客做网站运营国际网站怎么样做
  • 数据结构-算法C++(额外问题汇总)
  • 广州制作外贸网站邯郸wap网站建设公司
  • 在 Ubuntu22.04 进行envoy沙盒实验
  • 速卖通 item_get 接口对接全攻略:从入门到精通
  • diy建站系统windows 做网站服务器吗
  • 2025年--Lc171--H175 .组合两个表(SQL)
  • 贪心算法 | 每周8题(二)
  • 杭州知名的企业网站建设策划连云港吧
  • 建设工程网站有哪些黄骅贴吧最近发生的事
  • 广西网站建设招标公司如何用网站做招聘
  • 网络引流怎么做啊?百度关键词seo排名优化
  • 【开题答辩全过程】以 爱学习教育网站为例,包含答辩的问题和答案
  • 做旅游攻略去什么网站好广告设计与制作短期培训班
  • 搭建个人博客网站找国内外贸公司的网站
  • Halcon---3D知识点总结(待整理完善)
  • 速卖通自养号测评系统构建指南:三大核心技术要点解析
  • 中国城乡建设厅网站首页长沙企业推广
  • 手机上怎么做自己卖菜的网站大埔建设工程交易中心网站
  • 东莞网站建设做网站wordpress 思源黑体
  • 人声增强AI开源软件
  • 学校网站设计理念哪些网站可以做微商
  • 网站制作学生信息管理太原贴吧
  • C语言模拟面向对象编程方法之封装
  • 公司制作网站价格表莱芜生活网
  • 购物网站asp源码门户网站维护
  • 0.5 数据增强、keras模型保存以及读取、绘制loss过程
  • wordpress网站维护页面模板做网站材料
  • 8.复合查询与内外连接