[蓝桥杯学习]树上差分

差分

前缀和 sum_i = sum_i-1 + a_i

差分 diff_i = a_i - a_i-1

差分的好处

点的差分

问题引入
解决问题

要用到差分的思想,每次从叶子向上的回溯,让父结点+=子结点的cnt值,但是仅仅这样,还不行

回溯的过程中,LCA被加了两次,要减去一,LCA的父结点原本应该没有数值的,但是因为会加上LCA 的值,所以会多1,要减去。

此上操作,便实现了,只是把s t 两个结点的值赋一,便将s到t路径上的点经过次数赋值为1

代码实现

cnt计算的代码实现,如下

cpp 复制代码
void dfs1(int x){
    for(int i=head[x];i;i=edge[i].nex){
        int u=edge[i].to;
        if(u!=fa[x][0]){
            dfs1(u);
            cnt[x]+=cnt[u];
        }
    }
    return ;
}

cnt[x]+=cnt[u] ,在dfs1 之后,就是从子结点回到父结点后进行cnt相加。

边的差分

问题引入

将路上每条边都权值加z

解决问题

把边塞给点,边的权值放在点上,使用差分的方法,每次修改都是O(1)的时间复杂度,将最后的结果最坏下是O(n)遍历要求的区间,就可以得到区间权值和。

解释为什么要把 dlt[lca(u,v)]-=2x

因为根据方法,回溯时父结点会加上子结点的权值,所以LCA会加上左右两边的孩子的权值(即边的权值),根据我们给点权值的定义,意思是,会经过该边两次,但是该边没有经过两次,所以会减去2x

代码实现

与点上的差分一样的

时间复杂度分析

维护的时间复杂度是O(1),最后dfs一遍统计答案,最坏时间复杂度是O(n)

相关推荐
喵了meme11 分钟前
Linux学习日记24:Linux网络编程基础
linux·网络·学习
BullSmall13 分钟前
《庄子》导读
学习
HL_风神17 分钟前
设计原则之迪米特
c++·学习·设计模式
HL_风神20 分钟前
设计原则之合成复用
c++·学习·设计模式
Qhumaing2 小时前
C++学习:【PTA】数据结构 7-2 实验6-2(图-邻接表)
数据结构·c++·学习
好奇龙猫2 小时前
【日语学习-日语知识点小记-日本語体系構造-JLPT-N2前期阶段-第一阶段(1):再次起航】
学习
wdfk_prog3 小时前
[Linux]学习笔记系列 -- [fs]sysfs
linux·笔记·学习
菜的不敢吱声3 小时前
swift学习第5天
学习·ssh·swift
其美杰布-富贵-李3 小时前
TabNet: 注意力驱动的可解释表格学习架构
学习·表格数据·tabnet
im_AMBER4 小时前
Leetcode 98 从链表中移除在数组中存在的节点
c++·笔记·学习·算法·leetcode·链表