黑科技——树剖两次dfs转一次dfs!

黑科技——树剖两次\(dfs\)转一次\(dfs\)!

重所周知,树链剖分通常是要\(dfs?\)两次的,就像这样:

int Fa[N],dep[N],Sz[N],son[N];
void dfs1(int x,int pre){
    Fa[x]=pre,dep[x]=dep[pre]+1;
    Sz[x]=1;
    erep(i,G,x){
        int y=G.to[i];
        if(y==pre)continue;
        dfs(y,x);
        Sz[x]+=Sz[y];
        (Sz[y]>Sz[son[x]])&&(son[x]=y);
    }
}
int L[N],R[N],Id,top[N];
void dfs2(int x,int tp){
    top[x]=tp;
    if(son[x])dfs2(son[x],tp);
    erep(i,G,x){
        int y=G.to[i];
        if(y==Fa[x]||y==son[x])continue;
        dfs2(y,y);
    }
}

但是在一些\(n\)比较大并且的卡常毒瘤题中,我们如果使用了两次\(dfs\)就有可能会出现\(tle\)的情况。

在这时,若我们无法优化本质算法的情况下我们需要卡常。

怎么卡呢?利用\(dfs\)序:

代码如下:

int Fa[N],dep[N],Sz[N],son[N],L[N],R[N],Id[N],cnt,top[N];
void dfs1(int x,int pre){
    Fa[x]=pre,dep[x]=dep[pre]+1;
    Sz[x]=1,L[x]=++cnt,Id[cnt]=x;
    erep(i,G,x){
        int y=G.to[i];
        if(y==pre)continue;
        dfs(y,x);
        Sz[x]+=Sz[y];
        (Sz[y]>Sz[son[x]])&&(son[x]=y);
    }
    R[x]=cnt;
}
rep(i,1,n)top[Id[i]]=Id[i]==son[Fa[Id[i]]]?top[Fa[Id[i]]]:Id[i];

就这样我们只用了一次\(dfs\)就完成了树剖的预处理操作。

别小看这一个递归,他在\(n\)较大的情况下,可以快大概\(1\)倍。

原文地址:https://www.cnblogs.com/dsjkafdsaf/p/11825989.html

时间: 2024-11-09 15:47:06

黑科技——树剖两次dfs转一次dfs!的相关文章

ACM: FZU 2105 Digits Count - 位运算的线段树【黑科技福利】

FZU 2105  Digits Count Time Limit:10000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Practice Description Given N integers A={A[0],A[1],...,A[N-1]}. Here we have some operations: Operation 1: AND opn L R Here opn, L and R are integer

51nod1307(暴力树剖/二分&dfs/并查集)

题目链接: http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1307 题意: 中文题诶~ 思路: 解法1:暴力树剖 用一个数组 num[i] 维护编号为 i 的边当前最大能承受的重量. 在加边的过程中根据给出的父亲节点将当前边所在的链上所有边的num都减去当前加的边的重量, 注意当前边也要减自重. 那么当num首次出现负数时加的边号即位答案: 事实上这个算法的时间复杂度是O(n^2)的, 不过本题并没有出那种退化成单链的

二叉树的非递归遍历,还有一点黑科技

二叉树的前中后序遍历,可以用递归秒解,看起来不值一提.但如果不允许采用递归,要怎么实现呢? 还是先来看看递归算法的实现吧: def visit( root): if root is not null: #1 visit(root.left) #2 visit(root.right) #3 上面展示的代码中有三个位置(#1,#2,#3)可以用来插入访问当前节点的代码,分别对应了前中后三种遍历.这三种不同的设定,实际上表达的是访问节点的不同时机. 我们可以用进栈和出栈来模拟这些递归的过程,在跟#1,

【波兰黑科技(持续更新)】Small-Space Multiple-Pattern Matching

此文鸣谢lct1999与我一起翻译,给我提供了许多的帮助 Claris老司机昨天向我安利了这篇波兰黑科技论文,主要讲的是怎么使用Hash来做AC自动机能做的那些问题,那么为了黑科技事业的蓬勃发展我今天就来把它翻译一下.翻译进度可能会非常非常慢-.在线持久更新 翻译的不好的地方可能会非常多-可能很多地方都会是直译-只是给大家看这个论文提供一个参考罢了 语序懒得调整成汉语语序辣 如果某些地方有更好的翻译建议,请联系我. 不严格按照原论文的排版来翻译- Section1.引言 多串匹配问题,即在长度为

非常简单的js双向数据绑定框架(三):js model黑科技

初衷 之前我们要在js域更新model,需要这样: model.set('name', 'sub'); 这实在太土了... 我们希望像angularjs一样,直接: $scope.name = 'sub'; 然后bong, 视图就会更新!这样的黑科技必定是极好的. 目标 完成model更新黑科技 200行以内完成 实现 今次主要借鉴avalon"劫持"setter,getter的方法,链接:avalon简化版解读 虽说是简化过的avalon,还是挺难读的. 整理下思路,主要两大点: 1

POJ3417Network(LCA+树上查分||树剖+线段树)

Yixght is a manager of the company called SzqNetwork(SN). Now she's very worried because she has just received a bad news which denotes that DxtNetwork(DN), the SN's business rival, intents to attack the network of SN. More unfortunately, the origina

洛谷T3401 洛谷树 树剖&&分治

这道题好干燥啊...折腾了半个月...感谢bogo大佬对我的指导...题目要求支持的操作:1.查询某段路径的所有子路径的xor值之和:2.修改某条边的权值.重点是操作1.刚开始,我看到了操作1之后就不自觉的想到了非~常暴力的东西...还好大佬及时把我引上正途:分治! 大家知道,最大子段和有个分治算法,本题的方法就跟这个比较类似.对于一段子路径,若它能对答案产生贡献,那么它要么完全在左儿子中,要么完全在右儿子中,要么跨越左右儿子.对于每段路径,我们需要记录如下变量:yh:异或和,ans:答案,就是

POJ-1330&HDU-2586 最近公共祖先(不带权+带权)树剖式写法求LCA

其实敲树剖敲多了就会手敲,然后就发现其实树剖也是可以求LCA的,根据树剖的经验,我们两遍dfs后关于询问l,r的情况我们就开始跳链,当l,r处于同一个链的时候返回深度较小的那个点就好了,这里给个例题: 题目链接:http://poj.org/problem?id=1330 Description A rooted tree is a well-known data structure in computer science and engineering. An example is shown

2017黑科技趋势最具看点的十大新品

腾讯数码讯(Human)作为一年一度的全球消费电子市场风向标,今年同样在拉斯维加斯举办的CES 2017消费电子展,依然吸引了一大批全球各个领域的厂商参展,从科技巨头到初创小团队.从传统汽车厂商再到家电企业,似乎所有能与科技沾边的公司都希望能在CES 2017上好好展示一次自己的风采. 其实每年的CES都有一些明星产品给我们留下深刻的印象,今年的也不例外.而这些明星产品不仅仅只是单单一款产品,更是代表了各自行业在进入到2017年之后的一个发展趋势和方向.而就将这样的变化能否成为未来的主流.或只是