十几天前看到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. hdu_1006 Tick and Tick(暴力模拟)

    hdu1006 标签(空格分隔): 暴力枚举 好久没有打题了,退队了有好几个月了,从心底不依赖那个人了,原来以为的爱情戏原来都只是我的独角戏.之前的我有时候好希望有个人出现,告诉自己去哪里,做什么,哪 ...

  2. Choose the best route(最短路)dijk

    http://acm.hdu.edu.cn/showproblem.php?pid=2680 Choose the best route Time Limit: 2000/1000 MS (Java/ ...

  3. 数值积分之Simpson公式与梯形公式

    Simpson(辛普森)公式和梯形公式是求数值积分中很重要的两个公式,可以帮助我们使用计算机求解数值积分,而在使用过程中也有多种方式,比如复合公式和变步长公式.这里分别给出其简单实现(C++版): 1 ...

  4. mysql按照天统计报表,当天没有数据,填0

    1.问题复现: 按照天数统计每天的总数,如果其中有几天没有数据,那么group by 返回会忽略那几天,如何填充0?如下图,统计的10-3~10-10 7天的数据,其中只有8号和10号有数据,这样返回 ...

  5. 如何为图片添加热点链接?(map + area)

    所谓图片热点链接就是为图片指定一个或多个区域以实现点击跳转到指定的页面.简单来说就是点击某一区域就能跳转到相应的页面,而无需点击整个图片才能跳转. 说到图片热点链接,我首先想到了map + area, ...

  6. win处navicat直接导出的sql脚本导入Linux mysql报错问题

    最近几天在把win上的项目的数据库转移到Ubuntu,于是第一件事就是从win处的navicat直接导出sql脚本,然后进入Ubuntu导入的时候会报错误,跳过错误继续执行导致数据库表的缺失. 跨平台 ...

  7. 刚装上最新node,npm install报这个错误!求ndoe大神解答!!!

    npm -v和node-v都可以打印出来但是 npm install就报错! 解决方法:网络问题,建议使用cnpm install命令安装npm,再运行npm run dev 命令

  8. asp.net -mvc框架复习(4)-ASP.NET MVC中的约定规则

    1.路由规则 using System;using System.Collections.Generic;using System.Linq;using System.Web;using System ...

  9. 2018/1/27 每日一学 最长不降序子序列的O(n*logn)算法

    手动维护一个数组模拟即可,233-- 可以使用algorithm中的lower_bound(相当于二分) 代码如下: #include<cstdio> #include<algori ...

  10. shell 学习四十五天---xargs

    当 find 产生一个文件列表时,该列表提供给另一个命令有时是很有用的.案例: $touch abc.c erd.c oiy.c $ll ./erd.c ./abc.c ./oiy.c $find - ...