十几天前看到zyf2000发过关于这个的题目的Blog, 今天终于去学习了一下
[Codeforces原文链接](http://codeforces.com/blog/entry/44351#comment-332425)

dsu on tree

简介

我也不清楚dsu是什么的英文缩写...

好吧是Disjoint Set Union 并查集2333

就像是树上的启发式合并

用到了\(heavy-light\ decomposition\)树链剖分

把轻边子树的信息合并到重链上的点里

因为每次都是先dfs轻儿子再dfs重儿子,只有重儿子子树的贡献保留,所以可以保证dfs到每颗子树时当前全局维护的信息不会有别的子树里的,和莫队很像


算法过程

find the BigChild of each vertex
dfs(u, fa, keep)
dfs(LightChild, u, 0)
dfs(BigChild, u, 1), big[BigChild] = 1
update(u, fa, 1) //calculate the contribution of u's LightChild's SubTree
update the ans of u
big[BigChild] = 0
if keep == 0
update(u, fa, -1) //remove the contributino of u's SubTree update(u, fa, val)
calculate u's information
update(v : (u, v) and !big[v], u, val)

先递归计算轻儿子子树,递归结束时消除他们的贡献

再递归计算重儿子子树,保留他的贡献

再计算当前子树中所有轻子树的贡献

更新答案

如果当前子树是父节点的轻子树,消除当前子树的贡献


复杂度分析

显然只有遇到轻边才会把自己的信息合并到父节点

树链剖分后每个点到根的路径上有\(logn\)条轻边和\(lgon\)条重链

一个点的信息只会向上合并\(logn\)次

如果一个点的信息修改是\(O(1)\)的,那么总复杂度就是\(O(nlogn)\)

从这里我们可以发现和对dfs序使用莫队有异曲同工之妙,莫队也要求修改的复杂度很低


应用

  1. 优秀的dfs序莫队替代品,复杂度\(\sqrt{n} \rightarrow logn\)
  2. 结合点分治的思想可以做一些有根树上的路径统计问题

模板题

CF600E. Lomsat gelral

题意:询问每颗子树中出现次数最多的颜色们编号和

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
#define pii pair<int, ll>
#define MP make_pair
#define fir first
#define sec second
const int N=1e5+5;
int read(){
char c=getchar();int x=0,f=1;
while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
return x*f;
} int n, a[N];
struct edge{int v, ne;}e[N<<1];
int cnt, h[N];
inline void ins(int u, int v) {
e[++cnt]=(edge){v, h[u]}; h[u]=cnt;
e[++cnt]=(edge){u, h[v]}; h[v]=cnt;
}
int size[N], mx[N], big[N];
void dfs(int u, int fa) {
size[u]=1;
for(int i=h[u];i;i=e[i].ne)
if(e[i].v != fa) {
dfs(e[i].v, u);
size[u] += size[e[i].v];
if(size[e[i].v] > size[mx[u]]) mx[u] = e[i].v;
}
} int cou[N], Max; ll ans[N];
pii f[N];
void update(int u, int fa, int val) {
int &c = cou[a[u]];
f[c].fir --; f[c].sec -= a[u];
c += val;
f[c].fir ++; f[c].sec += a[u];
if(val==1) Max = max(Max, c);
else if(!f[Max].fir) Max--; for(int i=h[u];i;i=e[i].ne)
if(e[i].v != fa && !big[e[i].v]) update(e[i].v, u, val);
} void dfs(int u, int fa, int keep) {
for(int i=h[u];i;i=e[i].ne)
if(e[i].v != fa && e[i].v != mx[u]) dfs(e[i].v, u, 0);
if(mx[u]) dfs(mx[u], u, 1), big[mx[u]] = 1;
update(u, fa, 1);
ans[u] = f[Max].sec;
big[mx[u]] = 0;
if(!keep) update(u, fa, -1);
}
int main() {
//freopen("in","r",stdin);
n=read();
for(int i=1; i<=n; i++) a[i]=read();
for(int i=1; i<n; i++) ins(read(), read());
dfs(1, 0);
dfs(1, 0, 1);
for(int i=1; i<=n; i++) printf("%I64d ",ans[i]);
}

[dsu on tree]【学习笔记】的更多相关文章

  1. dsu on tree学习笔记

    前言 一次模拟赛的\(T3\):传送门 只会\(O(n^2)\)的我就\(gg\)了,并且对于题解提供的\(\text{dsu on tree}\)的做法一脸懵逼. 看网上的其他大佬写的笔记,我自己画 ...

  2. dsu on tree 学习笔记

    这是一个黑科技,考虑树链剖分后,每个点只会在轻重链之间转化\(log\)次. 考虑暴力是怎么写的,每次枚举一个点,再暴力把子树全部扫一边. \(dsu\ on\ tree.\)的思想就是保留重儿子不清 ...

  3. 珂朵莉树(Chtholly Tree)学习笔记

    珂朵莉树(Chtholly Tree)学习笔记 珂朵莉树原理 其原理在于运用一颗树(set,treap,splay......)其中要求所有元素有序,并且支持基本的操作(删除,添加,查找......) ...

  4. Codeforces 600E. Lomsat gelral(Dsu on tree学习)

    题目链接:http://codeforces.com/problemset/problem/600/E n个点的有根树,以1为根,每个点有一种颜色.我们称一种颜色占领了一个子树当且仅当没有其他颜色在这 ...

  5. Link Cut Tree学习笔记

    从这里开始 动态树问题和Link Cut Tree 一些定义 access操作 换根操作 link和cut操作 时间复杂度证明 Link Cut Tree维护链上信息 Link Cut Tree维护子 ...

  6. 矩阵树定理(Matrix Tree)学习笔记

    如果不谈证明,稍微有点线代基础的人都可以在两分钟内学完所有相关内容.. 行列式随便找本线代书看一下基本性质就好了. 学习资源: https://www.cnblogs.com/candy99/p/64 ...

  7. k-d tree 学习笔记

    以下是一些奇怪的链接有兴趣的可以看看: https://blog.sengxian.com/algorithms/k-dimensional-tree http://zgjkt.blog.uoj.ac ...

  8. splay tree 学习笔记

    首先感谢litble的精彩讲解,原文博客: litble的小天地 在学完二叉平衡树后,发现这是只是一个不稳定的垃圾玩意,真正实用的应有Treap.AVL.Splay这样的查找树.于是最近刚学了学了点S ...

  9. LSM Tree 学习笔记——本质是将随机的写放在内存里形成有序的小memtable,然后定期合并成大的table flush到磁盘

    The Sorted String Table (SSTable) is one of the most popular outputs for storing, processing, and ex ...

  10. LSM Tree 学习笔记——MemTable通常用 SkipList 来实现

    最近发现很多数据库都使用了 LSM Tree 的存储模型,包括 LevelDB,HBase,Google BigTable,Cassandra,InfluxDB 等.之前还没有留意这么设计的原因,最近 ...

随机推荐

  1. string::npos的一些说明

    一.定义 std:: string ::npos的定义: static const size_t npos = -1; 表示 size_t 的最大值( Maximum value for size_t ...

  2. 基于TypeScript装饰器定义Express RESTful 服务

    前言 本文主要讲解如何使用TypeScript装饰器定义Express路由.文中出现的代码经过简化不能直接运行,完整代码的请戳:https://github.com/WinfredWang/expre ...

  3. sublimeserver启动本地服务器(sublime text)

    今天又get到了一个新知识点,就是在sublime text上也可以模拟一个本地服务器的环境,前提是要先安装sublimeserver这个插件.这个插件的安装办法有两种. 1.我们可以直接在subli ...

  4. Tomcat之URL查找的过程

    Tomcat之URL查找的过程     webapps目录: tomcat共享目录.需要共享的本地资源放到此目录中.  

  5. sql子查询

    一.子查询入门: 1.单值子查询: 单值子查询的唯一限制:子查询的返回值必须只有一行记录,而且只能有一列(又被称为标量子查询). 可以使用在select语句的列表.表达式中,以及where语句中等. ...

  6. jquery自定义进度条与h5原生进度条

      介绍一款自定义的进度条 <div class="box-nine"> <div class="progress"> <!--一 ...

  7. Reflection and array

    java.lang.Reflect.Array类提供了动态创建和访问数组元素的各种静态方法. package com.sunchao.reflection; import java.lang.refl ...

  8. MyEclipse或Eclipse导出JavaDoc中文乱码问题解决

  9. python装饰器实现对异常代码出现进行监控

    异常,不应该存在,但是我们有时候会遇到这样的情况,比如我们监控服务器的时候,每一秒去采集一次信息,那么有一秒没有采集到我们想要的信息,但是下一秒采集到了, 而后每次的采集都能采集到,就那么一次采集不到 ...

  10. Django 中 makemigrations、migrate时 No changes detected

    Django创建的项目中,需要更改.增加.删除表中的某些属性,性急直接把之前数据库表删除了,之后再执行: python manage.py makemigrations python manage.p ...