dsu,对于无修改子树信息查询,并且操作支持undo的问题

暴力dfs,对于每个节点,对所有轻儿子dfs下去,然后再消除轻儿子的影响

dfs重儿子,然后dfs暴力恢复轻儿子们的影响,再把当前节点影响算进去

就有了整棵子树的信息了,时间复杂度O(nlogn)

经典例题:http://codeforces.com/contest/600/problem/E

 #include <bits/stdc++.h>

 using namespace std;

 typedef long long ll;

 const int N = 1e5 + ;

 int n, c[N];

 int cnt[N], maxCnt;

 int siz[N], son[N];

 vector <int> e[N];

 ll ans[N], sum[N];

 void dfs1(int u, int fr) {
siz[u] = ;
for (int v : e[u]) {
if (v == fr) continue;
dfs1(v, u);
siz[u] += siz[v];
if (siz[v] > siz[son[u]]) son[u] = v;
}
} void update(int x, int y) {
sum[cnt[x]] -= x;
cnt[x] += y;
sum[cnt[x]] += x;
if (cnt[x] > maxCnt) maxCnt = cnt[x];
if (sum[maxCnt] == ) maxCnt --;
} void dfs3(int u, int fr, int val) {
update(c[u], val);
for (int v : e[u]) {
if (v == fr) continue;
dfs3(v, u, val);
}
} void dfs2(int u, int fr) {
for (int v : e[u]) {
if (v == fr || v == son[u]) continue;
dfs2(v, u), dfs3(v, u, -);
}
if (son[u]) dfs2(son[u], u);
for (int v : e[u]) {
if (v == fr || v == son[u]) continue;
dfs3(v, u, );
}
update(c[u], );
ans[u] = sum[maxCnt];
} int main() {
ios::sync_with_stdio(false);
cin >> n;
for (int i = ; i <= n; i ++)
cin >> c[i];
for (int u, v, i = ; i < n; i ++) {
cin >> u >> v;
e[u].push_back(v);
e[v].push_back(u);
}
dfs1(, ), dfs2(, );
for (int i = ; i <= n; i ++)
cout << ans[i] << ' ';
cout << endl;
return ;
}

长链剖分,选择深度大的儿子作为重儿子

O(1)继承重儿子信息,然后按深度合并轻儿子信息

因为每个节点被作为轻链节点只会被合并一次,所以O(n)

例题:http://codeforces.com/problemset/problem/1009/F

 /* 长链剖分,选择深度最大的儿子作为重儿子,用于合并以深度为下标的信息
* 像 dsu 一样,直接继承重儿子信息,然后按深度暴力合并其他儿子信息
* 时间复杂度考虑每个节点作为轻儿子里的节点被合并只会有一次,所以 O(n)
* 另一种用法,可以 O(nlogn) 预处理后,O(1) 找到 k 级祖先
*/
int n;
int len[N], son[N], ans[N];
vector <int> e[N];
int tmp[N], *ptr, *f[N];
void dfs(int u, int fr) {
for (int v : e[u]) {
if (v == fr) continue;
dfs(v, u);
if (len[v] > len[son[u]]) son[u] = v;
}
len[u] = len[son[u]] + ;
}
void dp(int u, int fr) {
f[u][] = ;
if (son[u]) {
f[son[u]] = f[u] + ;
dp(son[u], u);
ans[u] = ans[son[u]] + ;
}
for (int v : e[u]) {
if (v == son[u] || v == fr) continue;
f[v] = ptr, ptr += len[v];
dp(v, u);
for (int j = ; j < len[v]; j ++) {
f[u][j + ] += f[v][j];
if ((f[u][j + ] > f[u][ans[u]]) || (f[u][j + ] == f[u][ans[u]] && j + < ans[u]))
ans[u] = j + ;
}
}
if (f[u][] >= f[u][ans[u]]) ans[u] = ;
}
int main() {
in(n);
for (int u, v, i = ; i < n; i ++) {
in(u), in(v);
e[u].push_back(v);
e[v].push_back(u);
}
dfs(, );
f[] = ptr = tmp, ptr += len[];
dp(, );
for (int i = ; i <= n; i ++)
printf("%d\n", ans[i]);
return ;
}

区分几种算法(dsu,树链剖分,树分治)用途:

树链剖分分为重链剖分和长链剖分

重链剖分应用比较多也比较常见不再赘述

当然dsu虽然也是一种应用但还是拿出来提一下把

下面的树分治仅仅针对点分治

dsu,长链剖分,点分治

三种都是无修改的树上信息查询算法

dsu应用限制:

只能统计子树中所有点的信息,并且操作必须支持删除

所以无法维护链的信息

长链剖分应用限制:

因为一般用于基于深度的信息合并

所以无法维护子树全部信息,只能维护深度相关信息

所以对于有边权的树一般都没有办法

树分治应用限制:

多用来树上路径的统计计数

缺点是无法像上述两种算法O(1)继承某个儿子的信息

所以可维护的信息种类相对有限

dsu+树链剖分+树分治的更多相关文章

  1. hdu 3966 Aragorn's Story(树链剖分+树状数组/线段树)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3966 题意: 给出一棵树,并给定各个点权的值,然后有3种操作: I C1 C2 K: 把C1与C2的路 ...

  2. Aragorn's Story 树链剖分+线段树 && 树链剖分+树状数组

    Aragorn's Story 来源:http://www.fjutacm.com/Problem.jsp?pid=2710来源:http://acm.hdu.edu.cn/showproblem.p ...

  3. 洛谷 P3384 【模板】树链剖分-树链剖分(点权)(路径节点更新、路径求和、子树节点更新、子树求和)模板-备注结合一下以前写的题目,懒得写很详细的注释

    P3384 [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节 ...

  4. HDU 3966 Aragorn's Story 树链剖分+树状数组 或 树链剖分+线段树

    HDU 3966 Aragorn's Story 先把树剖成链,然后用树状数组维护: 讲真,研究了好久,还是没明白 树状数组这样实现"区间更新+单点查询"的原理... 神奇... ...

  5. bzoj1146整体二分+树链剖分+树状数组

    其实也没啥好说的 用树状数组可以O(logn)的查询 套一层整体二分就可以做到O(nlngn) 最后用树链剖分让序列上树 #include<cstdio> #include<cstr ...

  6. HDU 5044 (树链剖分+树状数组+点/边改查)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5044 题目大意:修改链上点,修改链上的边.查询所有点,查询所有边. 解题思路: 2014上海网赛的变 ...

  7. BZOJ 1146: [CTSC2008]网络管理Network( 树链剖分 + 树状数组套主席树 )

    树链剖分完就成了一道主席树裸题了, 每次树链剖分找出相应区间然后用BIT+(可持久化)权值线段树就可以完成计数. 但是空间问题很严重....在修改时不必要的就不要新建, 直接修改原来的..详见代码. ...

  8. hdu 3966 Aragorn&#39;s Story(树链剖分+树状数组)

    pid=3966" target="_blank" style="">题目链接:hdu 3966 Aragorn's Story 题目大意:给定 ...

  9. (简单) POJ 3321 Apple Tree,树链剖分+树状数组。

    Description There is an apple tree outside of kaka's house. Every autumn, a lot of apples will grow ...

随机推荐

  1. Lightoj 1054 - Efficient Pseudo Code

    题目连接: http://www.lightoj.com/volume_showproblem.php?problem=1054 题目大意: 给出n,m,问n^m的所有因子之和是多少? 解题思路: 补 ...

  2. Tian Ji -- The Horse Racing HDU - 1052

    Tian Ji -- The Horse Racing HDU - 1052 (有平局的田忌赛马,田忌赢一次得200块,输一次输掉200块,平局不得钱不输钱,要使得田忌得到最多(如果只能输就输的最少) ...

  3. 贪心 Codeforces Round #109 (Div. 2) B. Combination

    题目传送门 /* 贪心:按照能选的个数和点数降序排序,当条件不符合就break,水题啊! */ #include <cstdio> #include <algorithm> # ...

  4. Objective-c单例模式的正确写法--用dispatch 线程安全

    单例模式在iOS开发中可能算是最常用的模式之一了,但是由于oc本身的语言特性,想要写一个正确的单例模式相对来说比较麻烦,这里我就抛砖引玉来聊一聊iOS中单例模式的设计思路.关于单例模式更多的介绍请参考 ...

  5. IOS编译报错:objc-class-ref in AppDelegate.o之解决方案 Xcode7

    Undefined symbols for architecture x86_64: "_OBJC_CLASS_$_QQApiInterface", referenced from ...

  6. 【Java】包装类型

    Java中的基本类型功能简单,不具备对象的特性,为了使基本类型具备对象的特性,所以出现了包装类,就可以像操作对象一样操作基本类型数据. 一.基本类型对应的包装类 基本类型                ...

  7. 关于使用myeclipse搭建tomcat环境运行web项目的方法

    这两天准备改同事的一个系统的自适应,然而我没想到的是我竟然在打开这个项目上就遇到了困难,真的是too young too simple,究其根本就是了解的太少了,于是为了我不忘记,用博客的方式把它记录 ...

  8. SQL Case 语句的使用

    -----简单case 使用 select 学号,姓名, case 专业 when '金融系' then '1' when '材料成型及控制工程' then '2' else '3' end from ...

  9. Apache Tomcat 之路(三 部署多个应用)

    想要在一台服务器上部署多个web应用的时候有两种部署方式:1.拷贝多个tomcat 服务器,每个服务器启动不同的web应用;2.一个tomcat容器部署多个web应用 两种方式的优缺点:多个tomca ...

  10. Farseer.net轻量级开源框架 中级篇:BasePage、BaseController、BaseHandler、BaseMasterPage、BaseControls基类使用

    导航 目   录:Farseer.net轻量级开源框架 目录 上一篇:Farseer.net轻量级开源框架 中级篇: UrlRewriter 地址重写 下一篇:Farseer.net轻量级开源框架 中 ...