世界真的很大
对于树上的询问要有意识地去想要不要吧树上问题转化成序列问题,就可以用线段树一类的数据结构来维护了
DFS序和树链剖分都是很不错的把树转换为序列问题的方法
看题先:
description
给一个树,树上每个节点都有两个属性:忠诚度和能力,给出若干查询,求每个子树中能力 > 树根能力的点中,忠诚度最高的那个
n≤50000
数值≤1000000
input
第一行一个整数T,表示数据组数
每一组数据第一行两个整数n,m,表示树有n个节点,有m组操作
接下来n-1行每行两个整数u,v,表示u,v之间有一条边
output:
对于每一个询问一个整数t表示答案,没有就输出-1
如果不管能力值得话,就相当于在一个数的子树里找一个忠诚度最高的,显然可以用DFS序后加以线段树解决,区间最大值而已
然后考虑怎么解决能力值得问题
仔细看来能力值并不是像忠诚度那样要求最大,只是需要大于当前查询的就行了,换句话就是说,只要能力值不比当前的大,不管是在子树外面还是里面,都对答案没有贡献,对于每一个人,有可能替代他的就只有能力值比他大的而已,再在这些人里面选一个在其子树里面忠诚度最高的
思路出来了,这个思路也是很重要的
对于两个要求条件,可以把其中一个只是范围要求的要求,排序。先建一颗空树,将能力值排序后再按忠诚度加入线段树,这样在查询任意一个人时,线段树里有的值都是比当前人能力值大的
完整代码:
#include<stdio.h>
#include<cstring>
#include<algorithm>
using namespace