树上差分

树上差分分析

使点x到点y的路径上(链上),全加上一个值,可以选择使用树上差分(不用线段树乱搞....

首先,和普通的差分一样,要有一个tag。然而,对于一个结点,我们需要求出它全部儿子的tag之后,才能算它的tag,进而算出它的值。所以,我们需要每个节点开一个tag(不然在依次遍历儿子的时候,轻儿子的tag不就乱了嘛...会影响的嘛)(前一个括号纯属口胡,就是一个博主的sb错误)

具体操作:(cf意为差分数组)

cf[x] + 1

cf[y] + 1

cf[ lca(x,y) ] - 1 //lca(x,y)算了两遍

cf[ fa[ lca(x,y) ] ] - 1 //为了不对其它的链产生影响

裸栗题

https://www.luogu.org/problem/P3258

这题注意一下: 如果出现这样的情况:x~y, y~z, 即连续进行差分, 需要注意:cf[y]加了两次,而这题中,y是不用加两次的,所以把ans[y]--,即可 (这个操作引题而异吧,自己多想想

#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXN = 300000+99;
const int MAXM = MAXN<<1; int n;
struct node{
int size, deep, son, tp, fa, cf, tag;
}a[MAXN];
int visit[MAXN]; int head[MAXN], cnt;
struct seg{
int y, next;
}e[MAXM];
void add_edge(int x, int y) {
e[++cnt].y = y;
e[cnt].next = head[x];
head[x] = cnt;
} void dfs1(int x, int fa) {
a[x].deep = a[fa].deep + 1;
a[x].fa = fa;
a[x].size = 1;
for(int i = head[x]; i; i = e[i].next)
if(e[i].y != fa) {
dfs1(e[i].y , x);
a[x].size += a[e[i].y].size ;
a[x].son = a[a[x].son].size > a[e[i].y].size ? a[x].son : e[i].y;
}
} void dfs2(int x, int tp) {
a[x].tp = tp;
if(a[x].son) dfs2(a[x].son , tp);
for(int i = head[x]; i; i = e[i].next)
if(e[i].y != a[x].fa && e[i].y != a[x].son) {
dfs2(e[i].y, e[i].y);
}
} int lca(int x, int y) {
while(a[x].tp != a[y].tp) {
if(a[a[x].tp].deep < a[a[y].tp].deep) swap(x, y);
x = a[a[x].tp].fa;
}
return a[x].deep < a[y].deep ? x : y;
} void dfs3(int x) {
if(a[x].son == 0) {
a[x].tag += a[x].cf;
// printf("tag_%d : %d\n",x, a[x].tag);
return ;
}
for(int i = head[x]; i; i = e[i].next)
if(e[i].y != a[x].fa) {
dfs3(e[i].y);
a[x].tag += a[e[i].y].tag ;
}
a[x].tag += a[x].cf ;//实际上还要在后面写上a[x].ans = ....
//但这题木有初值,所以我就直接用tag了
// printf("tag_%d : %d\n",x, a[x].tag); } int main() {
scanf("%d",&n);
for(int i = 1; i <= n; i++) scanf("%d",&visit[i]);
int x,y;
for(int i = 1; i < n; i++) {
scanf("%d%d",&x, &y);
add_edge(x,y);
add_edge(y,x);
}
dfs1(1, 0);
dfs2(1, 1);
int Lca;
for(int i = 1; i < n; i++) {
a[visit[i]].cf++;
a[visit[i+1]].cf++;
Lca = lca(visit[i], visit[i+1]);
a[Lca].cf--;
a[a[Lca].fa].cf--;
}
dfs3(1);
for(int i = 2; i <= n; i++) a[visit[i]].tag--;
for(int i = 1; i <= n; i++) printf("%d\n",a[i].tag);
// for(int i = 1; i <= n; i++) printf("cf_%d : %d\n",i, a[i].cf); return 0;
}
/*
5
1 4 5 3 2
1 2
2 4
2 3
4 5
*/

luoguP3258 [JLOI2014]松鼠的新家的更多相关文章

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

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

  2. [luoguP3258] [JLOI2014]松鼠的新家(lca + 树上差分)

    传送门 需要把一条路径上除了终点外的所有数都 + 1, 比如,给路径 s - t 上的权值 + 1,可以先求 x = lca(s,t) 类似数列上差分的思路,可以给 s 和 f[t] 的权值 + 1, ...

  3. BZOJ 3631: [JLOI2014]松鼠的新家( 树链剖分 )

    裸树链剖分... ------------------------------------------------------------------- #include<bits/stdc++ ...

  4. 3631: [JLOI2014]松鼠的新家

    3631: [JLOI2014]松鼠的新家 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 707  Solved: 342[Submit][Statu ...

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

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

  6. P3258 [JLOI2014]松鼠的新家

    P3258 [JLOI2014]松鼠的新家倍增lca+树上差分,从叶子节点向根节点求前缀和,dfs求子树和即可,最后,把每次的起点和终点都. #include<iostream> #inc ...

  7. 洛谷 P3258 [JLOI2014]松鼠的新家 解题报告

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

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

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

  9. [Luogu 3258] JLOI2014 松鼠的新家

    [Luogu 3258] JLOI2014 松鼠的新家 LCA + 树上差分. 我呢,因为是树剖求的 LCA,预处理了 DFN(DFS 序),于是简化成了序列差分. qwq不讲了不讲了,贴代码. #i ...

随机推荐

  1. [PHP] cli环境下php设置进程名字

    if (function_exists('cli_set_process_title')) { cli_set_process_title("superman php master proc ...

  2. Linux系统学习 八、SSH服务—SSH远程管理服务

    1.SSH简介 ssh(安全外壳协议)是Secure Shell的缩写,是建立在应用层和传输层基础上的安全协议.传输的时候是经过加密的,防止信息泄露,比telnet(明文传递)要安全很多. ftp安装 ...

  3. 转载:关于STM32硬件I2C读写EEPROM代码实现原理的理解与总结

    http://home.eeworld.com.cn/my/space-uid-716241-blogid-655190.html 一.I2C协议简介 I2C是两线式串行总线,用于连接微控制器及其外围 ...

  4. 不相交集ADT 你是和谁是一类人?

    //不相交集ADT (抽象数据类型) //一般用于集合运算 //用树,这种结构组成,有多个树(=森林) //属于同一颗数的元素,表示处于同一个集合中 //主要支持2个操作. //1. Find操作,找 ...

  5. [ Python入门教程 ] Python生成随机数模块(random)使用方法

    1.使用randint(a,b)生成指定范围内的随机整数.randint(a,b)表示从序列range([a,b])中获取一个随机数,包括b. >>> random.randint( ...

  6. 解决最新Java12 安装

    题外话: 因为我笔记本上的java用的版本是比较老的,从java8开始已经不再需要classpath java-home  path  这几个安装界的行业规范,基本上只需要安装 然后在path路径下 ...

  7. NOI2019退役记 upd:2019.12.1

    (我把原来写的东西全部删掉了) AFO. 我退役了,\(\mbox{yyb}\)退役了. 至少,在接下来的日子里,我得投身到文化课,度过快乐的高三生活了. 这两年的\(OI\)生涯给了我很多,让我学会 ...

  8. Vue修改单个组件的背景颜色

    组件默认背景颜色为白色,但工作需要改成黑色,于是研究了一番. 很简单,只需在组件中使用两个钩子函数beforeCreate (),beforeDestroy () 代码如下: beforeCreate ...

  9. Jenkins 有关 Maven 的内容

    Jenkins Maven 插件安装 在安装完 Jenkins 后,我们想添加新的项目 为 Maven 项目时,发现找不到这个选项. 原因是我们没有安装插件 Maven Integration. 在 ...

  10. C# MediaPlayer

    using System.Windows.Media; using Newtonsoft.Json; using System.ComponentModel; namespace ConsoleApp ...