dfs序专题
HDU 3887
题目要求
给出一棵树 root为p
对于每个结点输出它的子树中编号比它小的结点个数
参考AC代码
|
|
思路
dfs+树状数组
对于子树的操作 可以联想到dfs序
也运用到贪心的思想
从结点1开始每次进行sum操作后把该点加入到tree中 从结点小的开始依次插入可以确保答案正确
HDU 5692
题目要求
百度科技园内有n个零食机,零食机之间通过n−1条路相互连通。每个零食机都有一个值v,表示为小度熊提供零食的价值。
由于零食被频繁的消耗和补充,零食机的价值v会时常发生变化。小度熊只能从编号为0的零食机出发,并且每个零食机至多经过一次。
另外,小度熊会对某个零食机的零食有所偏爱,要求路线上必须有那个零食机。
为小度熊规划一个路线,使得路线上的价值总和最大。
输入数据第一行是一个整数T(T≤10),表示有T组测试数据。
对于每组数据,包含两个整数n,m(1≤n,m≤100000),表示有n个零食机,m次操作。
接下来n−1行,每行两个整数x和y(0≤x,y<n),表示编号为x的零食机与编号为y的零食机相连。
接下来一行由n个数组成,表示从编号为0到编号为n−1的零食机的初始价值v(|v|<100000)。
接下来m行,有两种操作:0 x y,表示编号为x的零食机的价值变为y;1 x,表示询问从编号为0的零食机出发 必须经过编号为x零食机的路线中 价值总和的最大值。
本题可能栈溢出,辛苦同学们提交语言选择c++,并在代码的第一行加上:
#pragma comment(linker, “/STACK:1024000000,1024000000”)
对于每组数据,首先输出一行”Case #?:”,在问号处应填入当前数据的组数,组数从1开始计算。
对于每次询问,输出从编号为0的零食机出发,必须经过编号为x零食机的路线中,价值总和的最大值。
参考AC代码
|
|
思路
dfs+线段树
题中需要求必须进过某点x 所以问题转换为求x子树中的结点到根节点的最大权值和
所以进一步转换为dfs序 用线段树维护权值和的最大值
因为这里的单点修改会影响到整棵子树进一步影响到整个线段树 所以实质是区间修改
本题的下标从0开始 方便计算我们全部+1
对于替换操作 实际上就是加上y-a[x] id数组记录的是序列是l的结点编号是多少 进一步取到dis的权值和
在dfs中可以顺带把dis求出(所有结点到根节点的权值和) 这里需要注意dis[1]初始化为a[1]
本题的2个注意点:
1.宏定义里mid不能写成m 会和原来的m参数交互
2.注意LR和lr的次数 因为粗心写反了调了1个小时
poj 3321(单点01修改+求子树的权值和)
fzu 2277(子树点权区间修改+单点查询)
HDU 5468
题目要求
一棵树 每个点都有一个点权 求每个结点的子树中结点与根节点互质的个数
参考AC代码
|
|
思路
这里root也算子树 所以return+1
子树用dfs序 其实就是在dfs序上求容斥 具体见注释
cf 620E
题目要求
一棵树 每个结点一种颜色 多次询问 每次询问两种操作
1.把结点v的子树结点颜色全部换成c
2.查询v的子树结点不同颜色的个数
参考AC代码
|
|
思路
对子树的操作 转化成dfs序
由于颜色只有60种 所以使用集合来表示颜色 不会爆LL
线段树进行维护和查询颜色 最后ans里1的个数就是不同颜色的个数
cf 877E
题目要求
一棵树 每个结点有一个01初始值
给出若干个操作
get x表示查询x的子树中1的个数
pow x表示把x的子树0变1 1变0
参考AC代码
|
|
思路
dfs序+线段树
线段树维护0的个数和1的个数以及异或的次数