luoguP3258 [JLOI2014]松鼠的新家
树上差分
树上差分分析
使点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]松鼠的新家的更多相关文章
- luoguP3258 [JLOI2014]松鼠的新家 题解(树上差分)
P3258 [JLOI2014]松鼠的新家 题目 树上差分:树上差分总结 #include<iostream> #include<cstdlib> #include<c ...
- [luoguP3258] [JLOI2014]松鼠的新家(lca + 树上差分)
传送门 需要把一条路径上除了终点外的所有数都 + 1, 比如,给路径 s - t 上的权值 + 1,可以先求 x = lca(s,t) 类似数列上差分的思路,可以给 s 和 f[t] 的权值 + 1, ...
- BZOJ 3631: [JLOI2014]松鼠的新家( 树链剖分 )
裸树链剖分... ------------------------------------------------------------------- #include<bits/stdc++ ...
- 3631: [JLOI2014]松鼠的新家
3631: [JLOI2014]松鼠的新家 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 707 Solved: 342[Submit][Statu ...
- [填坑]树上差分 例题:[JLOI2014]松鼠的新家(LCA)
今天算是把LCA这个坑填上了一点点,又复习(其实是预习)了一下树上差分.其实普通的差分我还是会的,树上的嘛,也是懂原理的就是没怎么打过. 我们先来把树上差分能做到的看一下: 1.找所有路径公共覆盖的边 ...
- P3258 [JLOI2014]松鼠的新家
P3258 [JLOI2014]松鼠的新家倍增lca+树上差分,从叶子节点向根节点求前缀和,dfs求子树和即可,最后,把每次的起点和终点都. #include<iostream> #inc ...
- 洛谷 P3258 [JLOI2014]松鼠的新家 解题报告
P3258 [JLOI2014]松鼠的新家 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他 ...
- 【洛谷】【lca+树上差分】P3258 [JLOI2014]松鼠的新家
[题目描述:] 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n(2 ≤ n ≤ 300000)个房间,并且有n-1根树枝连接,每个房间都可以相互到达,且俩个房间之间的路线都是唯一的.天哪,他居然真 ...
- [Luogu 3258] JLOI2014 松鼠的新家
[Luogu 3258] JLOI2014 松鼠的新家 LCA + 树上差分. 我呢,因为是树剖求的 LCA,预处理了 DFN(DFS 序),于是简化成了序列差分. qwq不讲了不讲了,贴代码. #i ...
随机推荐
- eNSP仿真软件之利用三层交换机实现VLAN间路由
1.实验原理: VLAN将一个物理的LAN在逻辑上划分成多个广播域.VLAN内的主机间可以直接通信,而VLAN间不能直接互通. 在现实网络中,经常会遇到需要跨VLAN相互访问的情况,工程师通常会选择一 ...
- mysql和oracle分页
mysql分页 关键字limit,limit m,n 其中m表示起始位置的下标,下标从0开始.n表示要显示的条数,比如要查询一个表的第2到5条数据. ,; oracle分页 关键字rownum, ro ...
- Mac--管理mysql、redis服务的常用命令
##启动MySQL服务 sudo /usr/local/MySQL/support-files/mysql.server start ##停止MySQL服务 sudo /usr/local/mysql ...
- 利用Runtime对Ivar实例变量进行共用的归档和解档方式
一.介绍 在OC中每一个对象持有的变量都是实例变量,实例变量包括成员变量和属性变量,在runtime中用Ivar表示对象的实例变量.其实,runtime源码中可以看到,Ivar也是一个结构体(基本上在 ...
- 用Python做个海量小姐姐素描图
素描作为一种近乎完美的表现手法有其独特的魅力,随着数字技术的发展,素描早已不再是专业绘画师的专利,今天这篇文章就来讲一讲如何使用python批量获取小姐姐素描画像.文章共分两部分: 第一部分介绍两种使 ...
- 踩过了这些坑,你真的懂python基础吗?
一.浮点数的计算 思考1:打印结果是什么? a = 0.1 b = 0.2 c = 0.3 print(b == a + a) 思考2:打印结果是什么? a = 0.1 b = 0.2 c = 0.3 ...
- PHP JWT token实现
原文链接:https://www.jb51.net/article/146790.htm 机制: 代码如下: <?php /** * PHP实现jwt */ class Jw ...
- oracle学习笔记(二十一) 程序包
程序包 之前我们调用的dbms_output.put_line(''),dbms_output就是一个程序包 程序包创建语法 1. 声明程序包 --声明程序包中的过程,函数,自定义的类型 --程序包里 ...
- 2019-6-5-WPF-拼音输入法
原文:2019-6-5-WPF-拼音输入法 title author date CreateTime categories WPF 拼音输入法 lindexi 2019-6-5 17:6:58 +08 ...
- C# 修改配置文件
/// <summary> /// 保存配置文件的设定 /// </summary> /// <param name="Key"></pa ...