这个算法还是挺人性化的,没有什么难度 就是可能看起来有点晕什么的。

大体 思想是 利用重链刨分来优化子树内部的查询。

考虑一个问题要对每个子树都要询问一次。我们暴力显然是\(n^2\)的。

考虑一下优化这个过程,我们发现儿子的信息可以给父亲用但是不能给兄弟或兄弟里的儿子用。

如果是最大最小值我们只能暴力来搞 但如果是出现次数什么的我们可以利用捅差分来解决这个事情。

考虑我们每次先暴力扫轻儿子然后 再做重儿子然后再把轻儿子的代价加上算当前节点的代价然后再把轻儿子的代价给删掉。

我们发现轻儿子被加上删掉两次 而重儿子只做一次并且保留。

可以发现这样做的复杂度很低 考虑一个点到根有logn条轻边所以这样最坏一个点被暴力来回扫logn次 统计自身答案的时候被扫了1次。

最终复杂度为nlogn 说起来很容易但其实代码还是存在一些细节的 要想好再写。

例题:CF600ELomsat gelral

const int MAXN=100010;
int n,len,mx;
int a[MAXN],cnt[MAXN],root[MAXN],sz[MAXN],son[MAXN];
int lin[MAXN],nex[MAXN<<1],ver[MAXN<<1];ll ans[MAXN],w;
inline void add(int x,int y)
{
ver[++len]=y;
nex[len]=lin[x];
lin[x]=len;
}
inline void dfs(int x,int father)
{
sz[x]=1;
for(int i=lin[x];i;i=nex[i])
{
int tn=ver[i];
if(tn==father)continue;
dfs(tn,x);
sz[x]+=sz[tn];
if(sz[son[x]]<sz[tn])son[x]=tn;
}
}
inline void update(int x,int father,int op,int target)
{
cnt[a[x]]+=op;
if(op>0&&cnt[a[x]]>=mx)
{
if(cnt[a[x]]==mx)w+=a[x];
else w=a[x],mx=cnt[a[x]];
}
for(int i=lin[x];i;i=nex[i])
{
int tn=ver[i];
if(tn==father||tn==target)continue;
update(tn,x,op,target);
}
}
inline void dfs(int x,int father,int op)
{
for(int i=lin[x];i;i=nex[i])
{
int tn=ver[i];
if(tn==father||tn==son[x])continue;
dfs(tn,x,0);//处理轻儿子的答案且清除
}
if(son[x])dfs(son[x],x,1);//处理重儿子的答案
update(x,father,1,son[x]);//把轻儿子的代价加入
ans[x]=w;//答案
if(!op)update(x,father,-1,0),w=0,mx=0;//当前是轻儿子所以删掉
}
int main()
{
freopen("1.in","r",stdin);
n=read();
for(int i=1;i<=n;++i)a[i]=read();
for(int i=1;i<n;++i)
{
int x,y;
x=read();y=read();
add(x,y);add(y,x);
}
dfs(1,0);
dfs(1,0,1);
for(int i=1;i<=n;++i)printf("%lld ",ans[i]);
return 0;
}

虽然这道题可以使用线段树合并来做但是那样对空间和时间的花销都是nlogn的 所以dsu on tree在空间上要优于线段树合并。

且 常数上也必然小于线段树合并。

我们只是关注与dsu on tree的思想 使用重链刨分来进行优化。

再来一道简单的题目来简单再看一下:CF208E Blood Cousins

求有多少个点和某个点的K级祖先相同。不难想到先求出K级祖先然后求出K级祖先子树内深度为x的点的个数。

关于K级祖先的求法:可以倍增+长链刨分优化实现O(1)但是仅对这道题就没什么必要了 询问和n同阶。

可以直接倍增搞,我们还有更快的方法:离线 我们dfs一个点然后加到栈中我们维护某条链上的点。

询问直接查栈中的从前往后第K个元素即可。

考虑第二问 求子树内深度为x的点的个数。显然 dsu on tree。

当然可以使用线段树合并,还有更快的方法:离线 开捅统计对于询问进行捅内外的差分。综上这道题被离线干成了O(n).

为了学习dsu on tree这里使用dsu on tree.

这道题 离线大法好 又得到了一个求树上K级祖先的方法 离线开栈。

const int MAXN=100010;
int n,len,mx,tot,top,m;
int a[MAXN],s[MAXN],cnt[MAXN],root[MAXN],sz[MAXN],son[MAXN];
int lin[MAXN],nex[MAXN],ver[MAXN],d[MAXN],ans[MAXN];
vector<pii>g[MAXN],w[MAXN];
inline void add(int x,int y)
{
ver[++len]=y;
nex[len]=lin[x];
lin[x]=len;
}
inline void dfs(int x,int father)
{
d[x]=d[father]+1;sz[x]=1;
s[++top]=x;
for(int i=0;i<g[x].size();++i)
{
int tn=g[x][i].F;
if(tn>d[father])continue;
int ss=s[top-tn];
w[ss].push_back(mk(d[x],g[x][i].S));
}
for(int i=lin[x];i;i=nex[i])
{
int tn=ver[i];
if(tn==father)continue;
dfs(tn,x);
sz[x]+=sz[tn];
if(sz[son[x]]<sz[tn])son[x]=tn;
}
--top;
}
inline void update(int x,int father,int op,int target)
{
cnt[d[x]]+=op;
for(int i=lin[x];i;i=nex[i])
{
int tn=ver[i];
if(tn==father||tn==target)continue;
update(tn,x,op,target);
}
}
inline void dfs(int x,int father,int op)
{
for(int i=lin[x];i;i=nex[i])
{
int tn=ver[i];
if(tn==father||tn==son[x])continue;
dfs(tn,x,0);
}
if(son[x])dfs(son[x],x,1);
update(x,father,1,son[x]);
for(int i=0;i<w[x].size();++i)
ans[w[x][i].S]+=cnt[w[x][i].F];
if(!op)update(x,father,-1,0);
}
int main()
{
freopen("1.in","r",stdin);
n=read();
for(int i=1;i<=n;++i)
{
int x=read();
if(!x)root[++tot]=i;
else add(x,i);
}
m=read();
for(int i=1;i<=m;++i)
{
int x,y;
x=read();y=read();
g[x].push_back(mk(y,i));
}
for(int i=1;i<=tot;++i)dfs(root[i],0);
for(int i=1;i<=tot;++i)dfs(root[i],0,0);//dsu on tree
rep(1,m,i)printf("%d ",ans[i]?ans[i]-1:0);
return 0;
}

dsu on tree详解的更多相关文章

  1. [CF1009F] Dominant Indices (+dsu on tree详解)

    这道题用到了dsu(Disjoint Set Union) on tree,树上启发式合并. 先看了CF的官方英文题解,又看了看zwz大佬的题解,差不多理解了dsu on tree的算法. 但是时间复 ...

  2. 【算法】关于图论中的最小生成树(Minimum Spanning Tree)详解

    本节纲要 什么是图(network) 什么是最小生成树 (minimum spanning tree) 最小生成树的算法 什么是图(network)? 这里的图当然不是我们日常说的图片或者地图.通常情 ...

  3. 二叉查找树(binary search tree)详解

    二叉查找树(Binary Search Tree),也称二叉排序树(binary sorted tree),是指一棵空树或者具有下列性质的二叉树: 若任意节点的左子树不空,则左子树上所有结点的值均小于 ...

  4. BTree和B+Tree详解

    https://www.cnblogs.com/vianzhang/p/7922426.html B+树索引是B+树在数据库中的一种实现,是最常见也是数据库中使用最为频繁的一种索引.B+树中的B代表平 ...

  5. ODT(old driver tree)详解(带例题)

    文章目录 ODT简介 实现前提&&实现原理 初始化 split操作 assign操作 其它操作 区间第k小 区间加 区间所有数的k次方和 几道水题 ODT简介 ODT(old driv ...

  6. 数据结构31:树(Tree)详解

    复制广义表数据结构中的树 树是数据结构中比较重要也是比较难理解的一类存储结构.本章主要主要围绕二叉树,对树的存储以及遍历做详细的介绍,同时还会涉及到有关树的实际应用,例如构建哈弗曼编码等. 由于树存储 ...

  7. 【2018.9.26】K-D Tree详解

    网上对K-D-Tree的讲解不尽清晰,我学了很久都不会写,这里新开一文做一些讲解. 1.K-D-Tree是什么? K-DTree 即 K-Dimensional-Tree,常用来作空间划分及近邻搜索, ...

  8. dsu on tree (树上启发式合并) 详解

    一直都没出过算法详解,昨天心血来潮想写一篇,于是 dsu on tree 它来了 1.前置技能 1.链式前向星(vector 建图) 2.dfs 建树 3.剖分轻重链,轻重儿子 重儿子 一个结点的所有 ...

  9. Ext.Net学习笔记22:Ext.Net Tree 用法详解

    Ext.Net学习笔记22:Ext.Net Tree 用法详解 上面的图片是一个简单的树,使用Ext.Net来创建这样的树结构非常简单,代码如下: <ext:TreePanel runat=&q ...

随机推荐

  1. elasticsearch集群配置 (Tobe Continue)

    elasticsearch集群配置 (Tobe Continue)   准备 首先需要在每个节点有可以正常启动的单节点elasticsearch   elasticsearch集群配置仅需要在elas ...

  2. CF833A The Meaningless Game 题解

    题目 Slastyona and her loyal dog Pushok are playing a meaningless game that is indeed very interesting ...

  3. NanoPi arm架构下的程序 ./ 运行黑屏 Qt环境可运行

    首先之所以QtCreator环境下可直接运行,但是在终端下 ./ 则不能运行(黑屏但是不报错),判断肯定不是程序或者是库的问题.于是猜想是环境问题,即终端环境与QtCreator环境不同. 然后就查看 ...

  4. git解决本地建立git仓库 连接远程git仓库出现拒绝合并问题

    (git解决本地建立git仓库 连接远程git仓库出现拒绝合并问题) 第一步在本地创建仓库 在本地创建一个文件夹,cd 进入创建的文件夹之后 git init 创建仓库 ,ls -a 能够看到 .gi ...

  5. 用Helm部署Kubernetes应用,支持多环境部署与版本回滚

    1 前言 Helm是优秀的基于Kubernetes的包管理器.利用Helm,可以快速安装常用的Kubernetes应用,可以针对同一个应用快速部署多套环境,还可以实现运维人员与开发人员的职责分离.现在 ...

  6. Spring Boot 2 实战:常用读取配置的方式

    1. 前言 在Spring Boot项目中我们经常需要读取application.yml配置文件的自定义配置,今天就来罗列一下从yaml读取配置文件的一些常用手段和方法. 2. 使用@Value注解 ...

  7. 【初学】Spring源码笔记之零:阅读源码

    笔记要求 了解Java语言 了解Spring Framework的基础 会使用Maven 关于本笔记 起因 本职数据分析,为公司内部人员开发数据处理系统,使用了Python/Django+Bootst ...

  8. java 数据结构(十一):Map接口

    双列集合框架:Map1.常用实现类结构 |----Map:双列数据,存储key-value对的数据 ---类似于高中的函数:y = f(x) * |----HashMap:作为Map的主要实现类:线程 ...

  9. 数据可视化实例(十一): 矩阵图(matplotlib,pandas)

    矩阵图 https://datawhalechina.github.io/pms50/#/chapter9/chapter9 导入所需要的库 import numpy as np # 导入numpy库 ...

  10. bzoj3384[Usaco2004 Nov]Apple Catching 接苹果*&&bzoj1750[Usaco2005 qua]Apple Catching*

    bzoj3384[Usaco2004 Nov]Apple Catching 接苹果 bzoj1750[Usaco2005 qua]Apple Catching 题意: 两棵树,每分钟会从其中一棵树上掉 ...