思路
题目要求在树上求最短路,我们很容易想到LCA来解决。
但问题我们需要同时计算能获得的最大值,所以我们需要额外的倍增数组来维护一些值。
那么具体是什么呢?
- 假设我们从$x$点出发,到达$LCA(x,y)$的时候,进行了买入操作,在$LCA(x,y)$到$y$的路上,进行了卖出操作,那么我们就需要直到$x-LCA(x,y)$上的最大值,$LCA(x,y)-y$上的最小值。所以我们需要两个倍增数组,一个$maxF$维护最大值,一个位置最小值$minF$(比如$maxF[x][i]$表示从$x$到它的$i$级祖先上最大值是多少)
- 假如我们直接在$x-LCA(x,y)$进行了买入卖出操作,那么我们需要直接计算这个最大值,设$up[x][i]$表示从$x$到它的$i$祖先进行了先买后卖操作所能获得最大值。那么我们怎么维护更新它呢?
设$y = f[x][i-1]$,那么最大值可能由以下三种情况中产生:- 在$x-y$中先卖后买,即$up[x][i-1]$
- 在$y - f[x][i]$中先买后卖,即$up[y][i-1]$
- 在$x-y$中买入,在$y - f[y][i-1]$中卖出,即$maxF[x][i-1] - minF[x][i-1]$
- 在$LCA(x,y) - y$中进行先买后卖操作,我们新开一个$down[x][i]$数组,含义与$up$类似,但注意,顺序不一样,这个表示从$x$的$i$级祖先到它本身,进行先买后卖操作。
一些细节
在求答案的过程中,使用了这种方式遍历倍增数组。
比如$9 = 2^3 + 2^0$,那么就会先执行$x’ = f[x][3]$,后执行$x’’ = f[x’][0]$
1 | for(int i = 20; i >= 0; --i) |
代码
1 |
|
- 本文作者: 水蓝络合物
- 本文链接: https://miku39393939.github.io/2022/04/06/LOJ6678/
- 版权声明: 本博客所有文章除特别声明外,均采用 MIT 许可协议。转载请注明出处!