随笔分类 - LCA
摘要:推荐技术公众号:不爱睡觉的大猪 好像LCA的题目并不多,现在就做了10道左右,但是找不到别的了,在此做个小总结,将来有更好的题目会不断更新 解决LCA问题,一般用3种方法 1.朴素方法:两个点都一直沿路径往上走,直到有某一个节点被经过两次并且是第一次出现这样的点,那么这个就是LCA 此方法最好理解,
阅读全文
摘要:LCA + 二分(很好的题目,思维难度和编程技巧兼具的一题,但是写起来又不会太麻烦,好题!)思路参考了网上题意:略,就是点间可以跳跃,但是不能越过两个点,每次跳跃的距离就是两点的距离 * 21.一般很容易想到,可以把一个状态看成一个点,那么状态间的转移就可以看做点间的连边,而且应该是无向边,应该两个状态是可以转化的。但是想到这里还不够,如果能想到这个图其实是个二叉树那么就完美了,而且应该说是一个无限深的二叉树,而且每个节点都有两个儿子,不会只有1个为什么会是一个二叉树,是因为对于每个状态,它都一定只会有3种或2种转移可能。对于一个状态,我们将3个点排好序,x < y < z如果y
阅读全文
摘要:LCA题意:单case,一棵无根树,输入点数和操作数,下面一行n个值代表每个点的权。下面n-1行是树边操作分为0 x w ,表示把点x的权改为wk a b , 求出,从a到b的路径中,第k大的点权这题,没什么太特别的地方,一开始写怕会超时,最后没有,就是直接按照题意来就可以了对于修改操作就直接修改对于查询第k个权的操作,先求出a,b的lca,然后将a到b路径上的点权都保存在一个数组中,然后降序排序,输出第k个元素即可#include <iostream>#include <cstdio>#include <cstring>#include <cmath
阅读全文
摘要:LCA题意:一个无根树,给出主角一开始所在的位置S,然后下面q个操作,操作包括查询和修改操作,对于查询操作就是当前主角的位置到目的点的距离是多少,然后主角去到那里之后就在那里等待,下次查询的时候那里就是新的起点(所以sample中第二次查询为什么是3)。修改是修改第k条边的权值,边的编号就是输入的顺序。这题可能是数据水了还是怎么,对于修改操作虽然有优化的方法,但是用最朴素的直接遍历下去修改也是可行的,不会超时,不过时间就比较糟糕了修改操作其实是修改了一部分子树的dir值,对于查询操作就是普通的LCA这里只能用RMQ了,不能用Tarjan#include <iostream>#inc
阅读全文
摘要:LCA参考Yuan神博客:/*题意:给出一棵节点有值的树,给出Q个询问(a,b),问从a到b的最大盈利(即:先在最小值买入,再在最大值卖出)我有想过用一个新序列w2-w1,w3-w2,,wn-wn-1这样只需用O(n)求得最大子段和即为结果Max-Min了但Q很大,每次都找一个路径会超时用类似Tarjan算法进行处理,但在find()那里要修改一下对每个几点记录4个值up[v]表示从v到目前的根的最大盈利down[v]从目前的根到v的最大盈利Max[v]表示到目前的根的最大值Min[v]表示到目前的根的最小值转移看update!在LCA(u,v)处再来计算,这样那四个值才是正确的值!!*/#i
阅读全文
摘要:LCA题意:先给出一棵无根树,然后下面再给出m条边,把这m条边连上,然后每次你能毁掉两条边,规定一条是树边,一条是新边,问有多少种方案能使树断裂。我们知道,这m条边连上后这颗树必将成环,假设新边为(u,v),那么环为u---->LCA(u,v)------->v-------->u,我们给这个环上的边计数1,表示这些边被一个环覆盖了一次。添加了多条新边后,可知树上有些边是会被多次覆盖的,画图很容易发现,但一个树边被覆盖了2次或以上,它就是一条牢固的边,就是说毁掉它再毁掉任何一条新边都好,树都不会断裂,这个结论也是很容易证明的,画图更明显,所以不累述所以这启发了我们,要统计所有
阅读全文
摘要:LCA题意:询问LCA,不过图不连通,如果两点不连通输出那串英文否则输出两点间的距离,模板题#include <iostream>#include <cstdio>#include <cstring>using namespace std;#define N 10010#define M 10010#define Q 1000010int head[N];struct edge{ int u,v,w,next;}e[2*M];int __head[N];struct ask{ int u,v,lca,next;}ea[2*Q];int dir[N],fa[N
阅读全文
摘要:连通分量+LCA题意:一个无向图可以有重边,下面q个操作,每次在两个点间连接一条有向边,每次连接后整个无向图还剩下多少桥(注意是要考虑之前连了的边,每次回答是在上一次的基础之上)首先运行一次tarjan,求出桥和缩点,那么远无向图将缩点为一棵树,树边正好是原来的桥。每次连接两点,看看这两点是不是在同一个缩点内,如果是,那么缩点后的树没任何变化,如果两点属于不同的缩点,那么连接起来,然后找这两个缩点的LCA,,因为从点u到LCA再到点v再到点u,将形成环,里面的树边都会变成不是桥。计数的时候注意,有些树边可能之前已经被标记了,这次再经过不能再标记首先按思路写了个代码,跑了2s多,因为显式建树了。
阅读全文
摘要:LCA题意:LCA模板题,输入n和m,表示n个点m条边,下面m行是边的信息,两端点和权,后面的那个字母无视掉,没用的。接着k,下面k个询问lca,输出即可有人说要考虑不连通的情况,我没考虑AC了,另外可能有u,u这样的询问,不过这不影响,照样是写模板,没有特判,一样能过还是Tarjan快一些LCA转RMQ在线算法#include <iostream>#include <cstdio>#include <cstring>#include <cmath>using namespace std;#define N 40010#define M 25in
阅读全文
摘要:LCA模板题题意:给一个无根树,有q个询问,每个询问两个点,问两点的距离。求出 lca = LCA(X,Y) , 然后 dir[x] + dir[y] - 2 * dir[lca]dir[u]表示点u到树根的距离下面两份代码都可以通过HDU的C++和G++,都不存在爆栈问题,网上很多人说会爆栈,加了申请系统栈语句,其实不用,而且好想比赛中不允许使用的Tarjan算法跑得更快些,C++ 15ms, G++ 50ms 左右, RMQ大概60ms在线算法:LCA转化为RMQ#include <iostream>#include <cstdio>#include <cst
阅读全文
摘要:LCA题意:给一个无根树,有q个询问,每个询问3个点,问将这3个点连起来,距离最短是多少,LCA的模板题,分别求LCA(X,Y),LCA(X,Z),LCA(Y,Z),和对应的距离,然后3个距离相加再除以2就是这个询问的结果对于一对点,x,y, lca = LCA(x,y) , 那么点x到点y的距离为 dir[x] + dir[y] - 2 * dir[lca] ; 其中dir[u] 表示点u到树根的距离由于是模板题,只给代码,详细的讲解可以在学习笔记里面找《LCA与RMQ》在线算法:LCA转RMQ#include <iostream>#include <cstdio>#
阅读全文