首页 > TAG信息列表 > Dsu
树上启发式合并(dsu on tree)
DSU on Tree and It's questions 树上启发式合并,可以在 \(O(n\log n)\) 的时间复杂度内解决一类对于子树的查询问题。这篇文章以题目为主。 算法流程 遍历 \(u\) 的所有轻儿子,计算答案,但不保留其在一个全局的数据结构内的结果。 遍历 \(u\) 的重儿子,保留它对一个全局数据结构的影并查集(dsu)
一共有 n 个数,编号是 1∼n ,最开始每个数各自在一个集合中。 现在要进行 m 个操作,操作共有两种: M a b,将编号为 a 和 b 的两个数所在的集合合并,如果两个数已经在同一个集合中,则忽略这个操作; Q a b,询问编号为 a 和 b 的两个数是否在同一个集合中; 输入格式 第一行输入整数 n 和 mABC EF 板刷笔记
菜鸡的刷题记录owo!偶尔也会更一些高质量D题。 ABC264 E 比较秒的一道题。 首先将操作反向处理,将摧毁变为修建,跑dsu维护答案即可。 总之就是先检查在不在一个连通块,然后发电厂就完了。启发式合并和DSU on tree入门
启发式合并 定义 一个基于直观或经验构造的算法,在可接受的花费(指计算时间和空间)下给出待解决组合优化问题每一个实例的一个可行解,该可行解与最优解的偏离程度一般不能被预计。 举个栗子:并查集的按秩合并。 每次我们将大集合合并到小集合里,新集合至少为大集合的两倍,每次合并都会变浅谈树上启发式合并(DSU on tree)
先看例题 CF600E Lomsat gelral 链接 对于这道题,我们要对每一个子树进行查询。观察一下,很容易想到通过信息的合并让父节点继承子节点的信息。但是对于每个点都开一个桶会MLE sol1 线段树合并 对于每一个节点都开一个线段树,然后进行线段树合并即可。这样做虽然足以通过本题,但空间巨dsu on tree
子树类查询问题 dsu on tree和长链剖分都是解决子树类静态查询问题的统计类算法。 这类问题首先要是“子树”查询,并且是“静态”不带修改的。 注意某些问题其实不太有必要上dsu on tree,比如子树元素和,子树元素最大值之类的。(可合并区间信息) 例如子树众数,子树元素种类数这些不可合树上启发式合并(dsu on tree)学习笔记
树上启发式合并(dsu on tree)学习笔记 闲话 树上启发式合并,又称 dsu on tree(虽然跟 dsu 并查集完全没关系),用于离线处理子树相关询问。 它是一种利用了重链剖分性质的暴力,时间复杂度为完全正确的 \(\mathcal{O}(n\log n+m)\),个人认为跟莫队等都是非常优雅的暴力。 阅读本文并不需要重leetcode(c++)(并查集)
#include <iostream> #include <vector> using namespace std; class DSU{ public: vector<int>parent; DSU(int n) { parent = vector<int>(n); for(int i = 0; i< n; ++i) { parent[i] =[dsu on tree] 2020CCPC长春F Strange Memory
首先考虑枚举lca的做法,对于每一个lca枚举其子树中所有节点,时间复杂度$O(n^2)$显然过不了 再思考发现这是一个针对子树的询问操作,考虑dsu on tree来统计答案 开一个新数组vec[x],其中x为权值,记录了所有权值为x的编号 那么只需要每次计算一颗新子树时,先累加答案,再更新vec数组(如果同时dsu on tree
算法简介 \(\quad\)前置知识:树链剖分 \(\quad\)dsu on tree 利用了树链剖分将重儿子先剖出来,然后在查询的时候先遍历轻儿子,然后将轻儿子所求的值删去(以免影响它的兄弟),最后求出重儿子,重儿子的贡献值因为是最后一个,所以不用清空,最后如果本节点是轻儿子,则清空自己,本节点是重儿子,则保Dsu on tree
dsu on tree学习笔记 (\(\uparrow\) 学习参考) 一般来说,Dsu on tree 大多可以和 点分治 互相换着用,都是处理子树或以 \(x\) 为根的路径等问题。 这种问题假设好状态基本上可以秒了。 咕咕咕Codeforces Round #762 (Div. 3) G. Unusual Minesweeper
题目 原题地址:G. Unusual Minesweeper 题目编号:1619G 目标算法:贪心、并查集 难度评分:2000 1.题目大意 有 n 个雷,每个雷都有自己的坐标 (x, y) 以及爆炸时间 所有雷都会按照 “+” 的形状爆炸,四个方向的波及范围均为 k 一个雷爆炸后如果其爆炸范围内有其他雷,则被波及的雷也会在【题解】CF1284G Seollal
前置芝士:拟阵交 如果你会,请跳过。 一切证明都略去了……如果需要的话我以后整理一个详细点的吧…… 拟阵的定义 我们记一个拟阵(Matroid) \(\mathcal M = \langle S,\mathcal I\rangle\)。 其中,我们称 \(S\) 为 Ground Set,\(\mathcal I\) 为 Family of Sets。 请注意此处的 \mathcal学习笔记:树上启发式合并(dsu on tree)
DSU on tree ! 解决树上问题的利器,复杂度虽然没有长链剖分优秀,不过思考简单而且代码优美,是树上维护答案的好帮手。 例题:DSU on tree 应用范围 解决一些子树的离线静态问题,巧妙地将暴力 \(O(n^2)\) 的复杂度优化到 \(O(nlogn)\)。 算法思路 回溯整棵树维护子树大小以及重儿子,为后牛客练习赛91 C.魔法学院(hard version) (dsu区间染色)
离线将所有信息存下来,按照字符的大小排序,不难发现,字符ascii越大的最后覆盖最优,那么我们选最大的覆盖,同时并查集维护覆盖过的区间,即让每个节点的父亲都等于它右边的节点,对于每个区间我们跑\([l_i,r_i]\),每次更新\(l\)为\(p[l+1]\),这样遇到覆盖过的区间就直接跳过,那么复杂度为\(O(n+DSU on tree
存一下,可以用来对比找bug #include<bits\stdc++.h> using namespace std; #define int long long void in(int &x){ int y=1;char c=getchar();x=0; while(c<'0'||c>'9'){if(c=='-')y=-1;c=getchar();} while(c<=Dsu on tree 和 点分治
写的有点乱,意识流 blog /yun 感谢 @Mr_Spade 对我的帮助。 从 Dsu on tree 到点分治 Dsu on Tree 的主要思想是轻重链剖分,使每个点作为根时,都继承重儿子的信息并快速加入根的影响,并对每个轻儿子暴力向重儿子合并。由于每个点被合并 \(O(\log n)\) 次,复杂度是正确的。 这种问题也可qbxt
d1:t1暴力 t2一开始看成l-r里随便选单个数异或小于x的数了,这个可以倍增归约二分套线段树,复杂度一个log 考虑对c排序,每次找差量,统计答案 对原序列差分,问题转化为每次异或两个点 然后我们发现除非两个点都被更新过否则直接乘 如果两个都更新过那么就找大的那个乘起来 然后你发现wa了,线段树分治 ---- CF1217F - Forced Online Queries Problem(假离线 可撤销并查集 + 线段树分治)详解
题目链接 题目大意 解题思路: 我一开始想到可以用可撤销并查集去维护这种删边加边的操作,但是有个缺点是每次撤销都有把后面的边全部撤销复度是 O ( nE - Moat(状压&DSU)
E - Moat(状压&DSU) 考虑每个位置是在区域内还是区域外,每个合法答案与区域的分布情况一一对应。 先状压,然后所有包含给定输入的情况,先将 4 × 4 4\timesU41492 树上数颜色(dsu on tree)
blackpink \(O(n^2)\)显然不过我们应该优化成\(O(nlogn)\) 采用树上启发式合并 仿照树链剖分的思想,对于每一个位置,我们先处理所有的轻儿子,然后处理重儿子,统计当前节点的答案,最后把轻儿子删掉就可以了。 这样全局一个桶就够用了。 #include<iostream> #include<cstdio> #include<al浅谈dsu on tree
前言:dsu on tree利用了树链剖分将重儿子先剖出来,然后在查询的时候先遍历轻儿子,然后将轻儿子所求的值删去(以免影响它的兄弟),最后求出重儿子,重儿子的贡献值因为是最后一个,所以不用清空,最后如果本节点是轻儿子,则清空自己,本节点是重儿子,则保留,依次。 dsu on tree利用了重儿子的性质,尽量CF741D Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths
题面传送门 这道题是dsu on tree的板子题。 我们考虑如果一个子串状压后1的个数小于等于\(1\)那么就肯定是回文串。 然后两个点之间路径的异或值就是两个点的前缀异或值。 那么直接dsu on tree即可。 dsu on tree的流程大概是先dfs轻子树然后删除贡献,然后dfs重子树保留贡献,然后dfsNote -「Dsu On Tree」学习笔记
前置芝士 树连剖分及其思想,以及优化时间复杂度的原理。 讲个笑话这个东西其实和 Dsu(并查集)没什么关系。 等等好像时间复杂度证明伪了?? 算法本身 Dsu On Tree,一下简称 DOT,常用于解决子树间的信息合并问题。 其实本质上可以理解为高维树上 DP 的空间优化,也可以理解为暴力优化。 在这CF570D Tree Requests 树上差分/dsu on tree
判断能否构成回文很简单,出现次数为偶数的不用管,出现次数为奇数的最多有一个 可以用状压储存出现次数的奇偶情况,判断的时候 puts(ans[i]==(ans[i]&(-ans[i]))?"Yes":"No"); 这里用到了树状数组的lowbit求法 解法一:dsu on tree裸题详情请见这里 解法二:树上差分 划重点:能用这种方法是