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

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

考虑一个问题要对每个子树都要询问一次。我们暴力显然是\(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. .NET 开源项目 StreamJsonRpc 介绍[中篇]

    阅读本文大概需要 11 分钟. 上一篇介绍了一些预备知识,包括 JSON-RPC 介绍和实现了 JSON-RPC 的 StreamJsonRpc 介绍,讲到了 StreamJsonRpc 可以通过 . ...

  2. [NOI2003]逃学的小孩 (贪心+树的直径+暴力枚举)

    Input 第一行是两个整数N(3 <= N <= 200000)和M,分别表示居住点总数和街道总数.以下M行,每行给出一条街道的信息.第i+1行包含整数Ui.Vi.Ti(1<=Ui ...

  3. opencv3.4.9 + armv7 + arm-linux-gnueabihf交叉编译

    使用CMake指定交叉编译链会有很多报错,原因可能是其找交叉编译的库或这头文件会自动链接到本地的库或者头文件. 可以使用Qt设置好交叉编译环境后,将CMakeLists.txt文件放入,直接编译通过即 ...

  4. 【Blazor】在ASP.NET Core中使用Blazor组件 - 创建一个音乐播放器

    前言 Blazor正式版的发布已经有一段时间了,.NET社区的各路高手也创建了一个又一个的Blazor组件库,其中就包括了我和其他小伙伴一起参与的AntDesign组件库,于上周终于发布了第一个版本0 ...

  5. Scala 面向对象(十):特质(接口) 三

    1 在特质中重写抽象方法特例 提出问题,看段代码 trait Operate5 { def insert(id : Int) } trait File5 extends Operate5 { def ...

  6. selenium.common.exceptions.WebDriverException:no such session

    应该是browser对象关闭之后你又使用了

  7. linux专题(七):账号管理

    http://dwz.date/UDf 简介 Linux系统是一个多用户多任务的分时操作系统,任何一个要使用系统资源的用户,都必须首先向系统管理员申请一个账号,然后以这个账号的身份进入系统. 用户的账 ...

  8. Lodash中数组常用方法

    数组方法 1.数组对象去重 differenceBy(array, [values], [iteratee=_.identity]) let newArr =_.differenceBy( [{ na ...

  9. Flutter 快捷开发 Mac Android Studio 篇

    老孟导读:此快捷方式适用于Mac下的 Android Studio .Windows 下的快捷方式请参考这篇文章:https://juejin.im/post/5efe71365188252e7d7f ...

  10. OSCP Learning Notes - WebApp Exploitation(5)

    Remote File Inclusion[RFI] Prepare: Download the DVWA from the following website and deploy it on yo ...