有一个关键信息就是
v
v
v一定是
u
u
u的祖先,也就是说从
u
u
u向根节点跳的时候一定可以到达
v
v
v
考虑用倍增处理,
d
p
[
i
]
[
j
]
dp[i][j]
dp[i][j]表示从
i
i
i向根节点走并且购买了
2
j
2^j
2j件物品的位置
转移也是正常的转移
d
p
[
i
]
[
j
]
=
d
p
[
d
p
[
i
]
[
j
−
1
]
]
[
j
−
1
]
dp[i][j]=dp[dp[i][j-1]][j-1]
dp[i][j]=dp[dp[i][j−1]][j−1]
关键在于
d
p
[
i
]
[
0
]
dp[i][0]
dp[i][0]的确定,
d
p
[
i
]
[
0
]
dp[i][0]
dp[i][0]的含义就是
i
i
i向上走第一个大于
a
[
i
]
a[i]
a[i]的位置
如果
a
[
f
a
]
>
a
[
u
]
a[fa]>a[u]
a[fa]>a[u]的话,那么
d
p
[
u
]
[
0
]
=
f
a
dp[u][0]=fa
dp[u][0]=fa
不然,就从
d
p
[
f
a
]
[
j
]
dp[fa][j]
dp[fa][j]进行倍增来找到
d
p
[
u
]
[
0
]
dp[u][0]
dp[u][0]
处理
d
p
dp
dp的过程用
d
f
s
dfs
dfs实现,所以在遍历到
u
u
u的时候,父节点
f
a
fa
fa的信息已经保留了。从
f
a
fa
fa向上跳,如果跳到某个点存在并且价值小于
u
u
u,跳到这个点后再向上跳;价值大于u的话,说明正确位置在该点下面的点,缩小
i
i
i继续跳。与正常的倍增一样,
i
i
i也要从大到小枚举
对于查询,可以将每次询问都增加一个节点
x
x
x到
u
u
u,
a
[
x
]
=
c
a[x]=c
a[x]=c,这样方便处理。然后从
x
x
x向
v
v
v跳,每次从大到小枚举
i
i
i,比较深度。由于每个数一定能拆成二进制数,所以一定可以跳到
v
v
v;每次的答案增加
2
i
2^i
2i