树上点差分的核心就是如何避免重复,即正确的运用差分数组

例如a,b点路径上点权值加1,则把a,b路径找到,并找到其LCA,此时可以把a到根,b到根这两条路径看出两条链,把每条链看出我们熟悉的

顺序差分结构.以其中一条链为例子,把a当成数组的起点,根当成数组的末尾,进行差分,显然有C[a]++,C[f[lca][0]]--(这里f[lca][0]为lca的父节点)

附上图片理解(摘自Oi-wiki)



故对a到b的路径上的差分修改的完整过程为C[a]++,C[b]++,C[lca]--(因为加了两次,要减去1次),C[f[lca][0]]--;

最后附上这条代码(里面还有一些具体应用的细节)

点击查看代码
//本题有点特殊,因为同时作为路径起点与终点的点差分值多算了一次,但仅限于点差分!!!
#include <bits/stdc++.h>
using namespace std;
typedef struct edge//链式前向星
{
int to,next;
}EDGE;
EDGE e[600005];//边
int head[300001];//以i为起点的第一条边
int cnt;//边的数量
int number[300001];//答案,同时兼具差分功能
int a[300001];//访问顺序
int f[300001][30];//倍增父节点
int depth[300001];//深度,服务于倍增
inline int read()//快读
{
int s = 0;
char ch = getchar();
while(ch > '9'||ch < '0') ch = getchar();
while(ch >= '0'&&ch <= '9')
{
s = s*10 + ch - '0';
ch = getchar();
}
return s;
}
void add(int x,int y)//加边
{
e[++cnt].to = y;
e[cnt].next = head[x];
head[x] = cnt;
}
void DFS(int x,int fa)//建树及预处理LCA
{
depth[x] = depth[fa] + 1;//深度加1
f[x][0] = fa;//第一个父节点
for (int i = 1;(1<<i)<=depth[x];i++)//倍增父节点
{
f[x][i] = f[f[x][i-1]][i-1];
}
for (int i = head[x];i;i = e[i].next)//遍历子树
{
if(e[i].to == fa) continue;
DFS(e[i].to,x);
}
}
void LCA(int a,int b)//求LCA兼具差分
{
if(depth[a]<depth[b]) swap(a,b);//不妨a的深度大于b
number[a]++;//差分思想
number[b]++;//差分思想
while(depth[a]>depth[b])//向上跳至深度相同
{
a = f[a][(int)(log(depth[a]-depth[b])/log(2))];//以后尽量不用用log写法,容易出错且不美观
}
if(a == b)
{
number[a]--;//祖先减1
number[f[a][0]]--;//祖先的父亲减1,这样保证了LCA只减了1
return;一定要返回
}
for (int i = (int)(log(depth[a])/log(2));i>=0;i--)//以后尽量不用用log写法,容易出错且不美观
{
if(f[a][i] != f[b][i])
{
a = f[a][i];
b = f[b][i];
}
}
number[f[a][0]]--;//同上原理
number[f[f[a][0]][0]]--;
}
void Solve(int x,int fa)//计算子树和
{
for (int i = head[x];i;i = e[i].next)
{
if(e[i].to == fa) continue;
Solve(e[i].to,x);
number[x] += number[e[i].to];//及求区间和,差分思想
}
}
int main()
{
int n = read();//读入节点数
for (int i = 1;i<=n;i++)//读入访问顺序
{
a[i] = read();
}
for (int i = 1;i<=n-1;i++)//建树
{
int x = read();
int y = read();
add(x,y);
add(y,x);
}
depth[0] = -1;
DFS(1,0);//预处理
for (int i = 1;i<=n-1;i++)//求LCA及差分
{
LCA(a[i],a[i+1]);
}
Solve(1,0);//计算子树和,计算区间和(注意这里是先计算区间和,再对多加点进行减法操作)
for (int i = 2;i<=n;i++) number[a[i]]--;//同时为起点终点的多加了一次,要减1,同时最后一点为餐厅,不用糖果,减1
for (int i = 1;i<=n;i++)//输出
{
printf("%d\n",number[i]);
}
return 0;
}

码字不易,多多支持!!

树上点差分的经典应用 LuoguP3258松鼠的新家的更多相关文章

  1. luoguP3258 [JLOI2014]松鼠的新家 题解(树上差分)

    P3258 [JLOI2014]松鼠的新家  题目 树上差分:树上差分总结 #include<iostream> #include<cstdlib> #include<c ...

  2. [BZOJ3631]:[JLOI2014]松鼠的新家(LCA+树上差分)

    题目传送门 题目描述: 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在“树”上.松鼠想邀 ...

  3. [填坑]树上差分 例题:[JLOI2014]松鼠的新家(LCA)

    今天算是把LCA这个坑填上了一点点,又复习(其实是预习)了一下树上差分.其实普通的差分我还是会的,树上的嘛,也是懂原理的就是没怎么打过. 我们先来把树上差分能做到的看一下: 1.找所有路径公共覆盖的边 ...

  4. 【洛谷】【lca+树上差分】P3258 [JLOI2014]松鼠的新家

    [题目描述:] 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n(2 ≤ n ≤ 300000)个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真 ...

  5. [JLOI2014] 松鼠的新家 (lca/树上差分)

    [JLOI2014]松鼠的新家 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在 ...

  6. 洛谷P3258 [JLOI2014]松鼠的新家(树上差分+树剖)

    题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在”树“上. 松鼠想邀请小熊维尼前 ...

  7. BZOJ3631 [JLOI2014]松鼠的新家 【树上差分】

    题目 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在"树"上.松鼠想 ...

  8. P3258[JLOI2014]松鼠的新家(LCA 树上差分)

    P3258 [JLOI2014]松鼠的新家 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他 ...

  9. BZOJ 3631: [JLOI2014]松鼠的新家 树上差分 + LCA

    Description 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在“树”上.松鼠想邀 ...

  10. 【bzoj3631】[JLOI2014]松鼠的新家 LCA+差分数组

    题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真的住在“树”上.松鼠想邀请小熊维尼前来 ...

随机推荐

  1. TimeLine 时间轴 网站 分享 time.graphics - nodejs 10年图

    话说20年 弹指一挥间 https://time.graphics/line/682014 nodejs 10年图 https://time.graphics/line/598790 资料 2022, ...

  2. 基于python的固定间隔时间执行实例解析

    一 概念 datetime的用法如下: import datetime. # 打印当前时间 time1 = datetime.datetime.now() print(time1) # 打印按指定格式 ...

  3. python数组概念和实例解析

    一 概念 如果我们需要一个只包含数字的列表,那么array.array比list更高效.数组支持所有跟可变序列有关的操作,包括.pop,.insert和.extend. 另外,数组还提供从文件读取和存 ...

  4. 记录--前端中 JS 发起的请求可以暂停吗

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 在前端中,JavaScript(JS)可以使用XMLHttpRequest对象或fetch API来发起网络请求.然而,JavaScrip ...

  5. 记录--Vue3 + Fabricjs 定制国庆专属头像

    这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 生在国旗下,长在春风里!国庆将至,采黎为大家带来 定制头像2.0(国庆头像),让我们用代码的形式为祖国庆生!欢迎大家点赞收藏加关注哦 前言 ...

  6. JS 为什么0==““ 会是true

    0 是逻辑的 false 1 是逻辑的 true空字符串是逻辑的 false null 是逻辑的 false NaN==任何 都是false 所以:空字符串是逻辑的 false , 0是逻辑的fals ...

  7. KingbaseES V8R6集群案例---一主二备架构单个备库宕机事务影响测试

    KingbaseES V8R6集群案例---一主二备架构单个备库宕机事务影响测试 案例说明: 对于KingbaseES V8R6集群,在sync模式下,对于一主一备架构,如果备库宕机时,主库事务com ...

  8. KingbaseES V8R6 运维案例 --flashback drop table

    一.KingbaseES V8R6 flashback drop table介绍 使用FLASHBACK删除和恢复表 删除表时,数据库不会立即删除与该表关联的空间.数据库重命名表,并将其和任何关联的对 ...

  9. 在 kubernetes 环境下如何优雅扩缩容 Pulsar

    背景 在整个大环境的降本增效的熏陶下,我们也不得不做好应对方案. 根据对线上流量.存储以及系统资源的占用,发现我们的 Pulsar 集群有许多的冗余,所以考虑进行缩容从而减少资源浪费,最终也能省一些费 ...

  10. 8分钟搞懂Java中的各种锁

    转载请注明出处️ 作者:测试蔡坨坨 原文链接:caituotuo.top/f9fc66cb.html 前言 你好,我是测试蔡坨坨. 在前几篇Redis相关文章中都说到了锁,同时我们在参加设计评审或者c ...