洛谷U41492(树上启发式合并)】的更多相关文章

(这题在洛谷主站居然搜不到--还是在百度上偶然看到的) 题目描述 给一棵根为1的树,每次询问子树颜色种类数 输入输出格式 输入格式: 第一行一个整数n,表示树的结点数 接下来n-1行,每行一条边 接下来一行n个数,表示每个结点的颜色c[i] 接下来一个数m,表示询问数 接下来m行表示询问的子树 输出格式: 对于每个询问,输出该子树颜色数 说明 对于前三组数据,1<=m,c[i]<=n<=100 1<=m,c[i]<=n<=1e5 本来在学树上启发式合并,偶然看到这个题,…
一直都没出过算法详解,昨天心血来潮想写一篇,于是 dsu on tree 它来了 1.前置技能 1.链式前向星(vector 建图) 2.dfs 建树 3.剖分轻重链,轻重儿子 重儿子 一个结点的所有儿子中拥有最多子树的儿子 轻儿子 一个结点的所有儿子中不是重儿子的儿子 重边 父亲与重儿子的连边 轻边 父亲与轻儿子的连边 重链 一堆重边连接而成的链 轻链 一堆轻边连接而成的链 2.什么是 dsu on tree(树上启发式合并) ? dsu on tree 其实就是个优雅的暴力算法,和它一起共被…
[洛谷U40581]树上统计treecnt 题目大意: 给定一棵\(n(n\le10^5)\)个点的树. 定义\(Tree[l,r]\)表示为了使得\(l\sim r\)号点两两连通,最少需要选择的边的数量. 求\(\sum_{l=1}^n\sum_{r=l}^nTree[l,r]\). 思路: 对于每个边考虑贡献,若我们将出现在子树内的点记作\(1\),出现在子树外的点记作\(0\),那么答案就是\(\frac{n(n-1)}2-\)全\(0\).全\(1\)串的个数.线段树合并,维护前缀/后…
树上启发式合并属于暴力的优化,复杂度O(nlogn) 主要解决的问题特点在于: 1.对于树上的某些信息进行查询 2.一般问题的解决不包含对树的修改,所有答案可以离线解决 算法思路:这类问题的特点在于父节点的信息是通过子节点更新而来 所以如果是暴力解决的话就是对每一个节点往下跑一次图,复杂度在O(n^2) 因为父节点是有子节点跟新而来,所以我们可以考虑每次保留一部分子节点的信息,将另一部分子节点信息暴力合并得到父节点的信息 这样的话我们就考虑保留重子节点的信息(子树中子节点数最多的节点),这样我们…
近几天跟着dreagonm大佬学习了\(dsu\ on\ tree\),来总结一下: \(dsu\ on\ tree\),也就是树上启发式合并,是用来处理一类离线的树上询问问题(比如子树内的颜色种数)的不二法宝.它不仅好想好写,还有着\(O(nlogn)\)的优秀时间复杂度(划重点). 结合一道例题来讲吧: CF600E Lomsat gelral 题目大意: 一棵树有\(n(n\leqslant 10^5)\)个结点,每个结点都是一种颜色,每个颜色有一个编号,求树中每个子树的最多的颜色编号的和…
有丶难,学到自闭 参考的文章: zcysky:[学习笔记]dsu on tree Arpa:[Tutorial] Sack (dsu on tree) 先康一康模板题吧:CF 600E($Lomsat$ $gelral$) 虽然已经用莫队搞过一遍了(可以参考之前写的博客~),但这个还是差距挺大 我们如果对于每个节点暴力统计答案,是$O(N^2)$的复杂度:最坏情况下整棵树是一条链,对于每个节点的统计平均下来是$O(N)$的 具体是怎么做的呢? 对于以当前节点$x$为根的子树,我们建立$cnt$和…
参考资料 https://www.cnblogs.com/zhoushuyu/p/9069164.html https://www.cnblogs.com/candy99/p/dsuontree.html https://www.cnblogs.com/zcysky/p/6822395.html 简介 树上启发式合并 用到了heavy−light decomposition树链剖分 把轻边子树的信息合并到重链上的点里 因为每次都是先dfs轻儿子再dfs重儿子,只有重儿子子树的贡献保留,所以可以保…
hdu6191 题意 给你一棵带点权的树,每次查询 \(u\) 和 \(x\) ,求以 \(u\) 为根结点的子树上的结点与 \(x\) 异或后最大的结果. 分析 看到子树,直接上树上启发式合并,看到异或,上 \(Trie\) . 这道题就是两个经典的题目结合了一波. 树上启发式合并处理这种需要查询整个子树的题目尤其有用,可以复用大量的信息. 离线查询后,到要查询的结点直接在 \(Trie\) \(01\) 树上跑一下即可. 先去理解一波 树上启发式合并(\(dsu \ on \ tree\))…
208E - Blood Cousins 题意 给出一棵家谱树,定义从 u 点向上走 k 步到达的节点为 u 的 k-ancestor.多次查询,给出 u k,问有多少个与 u 具有相同 k-ancestor 的节点. 分析 设 rt 为 u 的 k-ancestor.问题可以转换成在以 rt 为根的子树下,有多少个节点的深度与 u 相同. 预处理出离 u 距离为 k 的祖先 rt . 我们可以把所有的查询用向量存起来(祖先节点,要查询的节点的深度,对应查询的id),在遍历到某个祖先节点时,统计…
600E - Lomsat gelral 题意 给出一颗以 1 为根的树,每个点有颜色,如果某个子树上某个颜色出现的次数最多,则认为它在这课子树有支配地位,一颗子树上,可能有多个有支配的地位的颜色,对每颗子树分别求有支配地位的颜色的和(把颜色这个权值相加). 分析 树上启发式合并模板题. 参考blog1 参考blog2 复杂度证明 如果暴力去搜索,显然是 \(O(n^2)\) 的算法,可以考虑优化,当我们搜索到节点 u 时,最后去搜索 u 的子节点中子树节点数量最大的子节点(树链剖分求出重儿子)…
csu1811 题意 给定一棵树,每个节点有颜色,每次仅删掉第 \(i\) 条边 \((a_i, b_i)\) ,得到两颗树,问两颗树节点的颜色集合的交集. 分析 转化一下,即所求答案为每次删掉 \(u\) 和 \(u\) 的父亲节点所连的边后形成的两颗子树的颜色集合的交集. 那么我们要求的其实和 \(u\) 的子树有关.子树的状态(颜色数量信息)是可以复用的. 可以套用 树上启发式合并 ,固定 1 为根节点,从上往下搜,每次保留子节点中节点最多的那颗子树的状态(颜色数量信息),也就是在计算当前…
学习:http://codeforces.com/blog/entry/44351 E. Lomsat gelral 题意: 给定一个以1为根节点的树,每个节点都有一个颜色,问每个节点的子树中,颜色最多的是哪几种颜色,输出这些颜色的值得和. 思路: 树上启发式合并的模板题,具体来说,先对树进行树链剖分,分出一个重链和轻边,dfs时,把每条轻儿子暴力加到根节点中,每次加的时候,用这样的技巧 if(csz < cnt[col[v]]) sum = col[v] , csz = cnt[col[v]]…
点此看题面 大致题意: 给你两棵\(n\)个点的树,对于第一棵树中的每条边\(e_1\),求存在多少条第二棵树中的边\(e_2\),使得第一棵树删掉\(e_1\)加上\(e_2\).第二棵树删掉\(e_2\)加上\(e_1\)后皆仍为生成树. 题意转化 考虑对于\(e_1(x,y)\),合法的\(e_2(u,v)\),必然存在于第二棵树中\(x\)到\(y\)的路径之上. 同理,则\(e_1\)也应该存在于第一棵树中\(u\)到\(v\)的路径之上. 考虑到我们是在枚举\(e_1\),而每条边都…
[Codeforces600E] Lomsat gelral(树上启发式合并) 题面 给出一棵N个点的树,求其所有子树内出现次数最多的颜色编号和.如果多种颜色出现次数相同,那么编号都要算进答案 N≤100000 分析 树上启发式合并,用map记录颜色出现次数,合并的时候更新最多的出现次数和编号和. 注意合并时的下标问题.当我们merge(x,y)的时候,由于是启发式合并,s[x]可能会并到s[y]去,如果我们直接查询s[x],就查不到真正的答案.所以要再建立一个数组id[x],记录x的map合并…
题目链接 题目大意:给出一颗含有$n$个结点的树,每个节点有一个颜色.求树中每个子树最多的颜色的编号和. ------------------------- 树上启发式合并(dsu on tree). 我们先考虑暴力怎么做.遍历整颗树,暴力枚举子树然后用桶维护颜色个数.这样做是$O(n^2)$的,显然会T.我们需要一种更快的算法:树上启发式合并. 关于启发式算法的介绍,详见OI Wiki.本文只介绍树上启发式合并算法.本题的解法: 每处理完一颗子树,我们都要把桶清空一次,以免对它的兄弟造成影响.…
题目戳我 \(\text{Solution:}\) 树上启发式合并,是对普通暴力的一种优化. 考虑本题,最暴力的做法显然是暴力统计每一次的子树,为了避免其他子树影响,每次统计完子树都需要清空其信息. 但是,如果我们先对非\(x\)的节点进行统计,最后统计\(x\)然后合并其他节点的信息,那么,\(x\)的统计信息就没有必要被删掉. 那么显然地,\(x\)的子树越大越好. 于是,自然想到轻重链剖分,并将\(x\)设置为其重儿子.于是,算法模型如下: 对所有非重儿子进行统计并清空其所记录的统计信息.…
题目描述 一棵根为\(1\) 的树,每条边上有一个字符(\(a-v\)共\(22\)种). 一条简单路径被称为\(Dokhtar-kosh\)当且仅当路径上的字符经过重新排序后可以变成一个回文串. 求每个子树中最长的\(Dokhtar-kosh\)路径的长度. 输入输出样例 输入 #1 4 1 s 2 a 3 s 输出 #1 3 1 1 0 输入 #2 5 1 a 2 h 1 a 4 h 输出 #2 4 1 0 1 0 分析 一道树上启发式合并的好题 首先,我们来考虑什么样的情况下路径上的字符重…
(题面不是来自Luogu) 题目描述 有一个大小为n且以1为根的树,树上每个点都有对应的颜色ci.现给出m次询问v, k,问以v为根的子树中有多少种颜色至少出现了k次. 输入格式 第一行两个数n,m表示树的大小以及询问的次数. 第二行n个数表示树上每个结点的颜色. 接下来的n-1行,每行两个数a, b表示树上的边. 接下来m行,每行两个数v, k表示询问. 输出格式 m行,每行一个数表示第i次询问的答案. 样例输入1 8 5 1 2 2 3 3 2 3 3 1 2 1 5 2 3 2 4 5 6…
提交通道 洛谷日报 考虑非\(O(n^2)\)的预处理.一遍dfs时,check某颜色有没有的数组何时清空很尴尬:得到某树答案后如果不清,则影响接下来兄弟树的搜索:如果清了,父亲节点又难以收集答案. 解决方法:先让儿子们各顾各的家,算一遍各自的答案(假如能算),check清就清了吧.然后考虑人为优化,即重链求完后等一等!先别清!然后将轻链重新扫一遍,也不清check数组的.代码中的keep就控制是否要清.这样轻链扫两遍,重链扫一遍,就得到了儿子们和父亲的答案,随机数据下复杂度\(O(nlogn)…
题意:求每一个子树存在最多颜色的颜色代号和(可重复) 本题是离线统计操作,因此可以直接合并重儿子已达到\(O(nlogn)\)的复杂度 PS.不知道什么是启发式合并的可以这样感受一下:进行树链剖分,分出重儿子和轻儿子,每次离线dfs时保留重儿子得出的贡献,清除轻儿子的贡献并重新遍历 (反正是一种取代树上莫队的简单粗暴玩意,但是效率贼tm好) 唯一不解的小细节是似乎我在轻儿子的撤销操作中更新tmp存在问题,改了另一种写法就A了 想不出反例,求指教 Update:看出来了,是我傻缺.. #inclu…
F. Dominant Indices 题意: 给一颗无向树,根为1.对于每个节点,求其子树中,哪个距离下的节点数量最多.数量相同时,取较小的那个距离. 题目: 这类题一般的做法是树上的启发式合并,复杂度是O(nlogn).但由于这题所求的信息与深度有关,因此可以使用长链剖分的技巧,复杂度可以是O(n). 长链剖分可以维护以深度为下标的信息.先预处理,以深度为依据,标记长儿子.维护答案时,对于每个节点,O(1)继承其长儿子的信息.然后暴力合并其他儿子.则时间复杂度是所有长链的长度之和,即O(n)…
题目链接 题意:统计树上每个结点中恰好出现了k次的颜色数. dsu on tree/线段树合并裸题. 启发式合并1:(748ms) #include<bits/stdc++.h> using namespace std; typedef long long ll; ; int n,m,k,a[N],b[N],nb,fa[N],son[N],siz[N],cnt[N],ans[N],now,ne,hd[N],ka; ]; void addedge(int u,int v) {e[ne]= {v,…
洛谷P1880 石子合并 纪中2119. 环状石子归并 洛谷传送门 题目描述1 在一个圆形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分. 试设计出1个算法,计算出将N堆石子合并成1堆的最小得分和最大得分. 输入格式 数据的第1行试正整数N,1≤N≤100,表示有N堆石子.第2行有N个数,分别表示每堆石子的个数. 输出格式 输出共2行,第1行为最小得分,第2行为最大得分. 输入输出样例 输入 #1复制 4 4…
dsu on tree 本质上是一个 启发式合并 复杂度 \(O(n\log n)\) 不支持修改 只能支持子树统计 不能支持链上统计- 先跑一遍树剖的dfs1 搞出来轻重儿子- 求每个节点的子树上有多少颜色为k的节点 有一个朴素的\(N^2\)暴力做法- 每个点来个\(dfs\) 没了 好您会dfs序 主席树/莫队 您赢了?但是并没有dsu on tree 好打.. 每次加入 \(x\) 点的时候 考虑暴力将 \(x\) 的子树放入 然后取出 消除贡献- 所以先统计轻儿子 然后再统计重儿子 最…
题目描述 有一棵 \(n\) 个结点的以 \(1\) 号结点为根的有根树. 每个结点都有一个颜色,颜色是以编号表示的, \(i\) 号结点的颜色编号为 \(c_i\)​. 如果一种颜色在以 \(x\) 为根的子树内出现次数最多,称其在以 \(x\) 为根的子树中占主导地位.显然,同一子树中可能有多种颜色占主导地位. 你的任务是对于每一个 \(i\in[1,n]\),求出以 \(i\) 为根的子树中,占主导地位的颜色的编号和. \(n≤10^5,c_i\le n\) 输入输出样例 输入 #1 4…
P3177 [HAOI2015]树上染色 题目描述 有一棵点数为\(N\)的树,树边有边权.给你一个在\(0\) ~ \(N\)之内的正整数\(K\),你要在这棵树中选择\(K\)个点,将其染成黑色,并将其他的\(N-K\)个点染成白色 . 将所有点染色后,你会获得黑点两两之间的距离加上白点两两之间的距离的和的受益.问受益最大值是多少. 输入输出格式 输入格式: 第一行包含两个整数 \(N, K\) .接下来 \(N-1\) 行每行三个正整数 \(fr, to, dis\) , 表示该树中存在一…
解:首先有个套路是一条边的权值是[两端点颜色不同].这个用树剖直接维护,支持修改. 每次询问建虚树,查询虚树上每条边的权值.然后树形DP,用开店的方法,每个点链加链查. #include <bits/stdc++.h> #define forson(x, i) for(int i = e[x]; i; i = edge[i].nex) typedef long long LL; ; struct Edge { int nex, v; LL len; }edge[N << ], ED…
区间DP模板题 区间DP模板Code: ;len<=n;len++) { ;i<=*n-;i++) //区间左端点 { ; //区间右端点 for(int k=i;k<j;k++) //断点位置 { f[i][j] = min(f[i][j],f[i][k] + f[k + ][j] + s[j] - s[i - ]); } } } 题目描述 在一个园形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分.…
传送门 https://www.cnblogs.com/violet-acmer/p/9852294.html 题解: 这道题是石子合并问题稍微升级版 这道题和经典石子合并问题的不同在于,经典的石子合并问题是一排,而此问题是一个圈,也就意味着最后一堆石子可已选择第一堆石子,那这要怎么做呢? 其实方法很简单,在n堆石子后额外增加(n-1)堆石子,这(n-1)堆石子不是随意造的,其个数与前(n-1)堆石子一一对应. 然后,就是经典的石子合并问题了. 对于 1 到 2*n-1堆石子,进行区间最优解的查…
传送门 题解 因为一个sb错误调了一个晚上……鬼晓得我为什么$solve(rt)$会写成$solve(v)$啊!!!一个$O(logn)$被我硬生生写成$O(n)$了竟然还能过$5$个点……话说还一直以为只有动态点分会很难没想到一般点分都这么可啪……%%%大佬 我们考虑一下,对于一棵树,我们要处理的是子树对根的答案的贡献,以及经过根的路径的贡献(也就是$LCA$为根的点对的答案). 对于树中的一个点$i$,如果$i$的颜色是在$i$到根的路径上第一次出现,那么所有与$i$的$LCA$为根的点,都…