远期情景树上累计 PnL 越过门槛的叶节点计数
Win-Count Leaves on a Forward Scenario Tree
开始编码输入是一棵以两个平行层序数组形式给出的远期情景树,外加一个目标门槛值。parent_idx[i] 是节点 i 的父节点 index;parent_idx[0] = -1 标记根。node_pnl[i] 是节点 i 处实现的带符号 PnL 增量(根的 node_pnl[0] 是它自己的起始前缀贡献)。实现 solution(parent_idx: list[int], node_pnl: list[float], threshold: float) -> int,返回根到叶累计路径和严格大于 threshold 的叶节点个数。
节点 i 是叶节点,当且仅当没有其它节点把 i 列为父亲。树可以是二叉的,也可以是一般树(多个节点共享同一父节点是允许的)。由于 parent_idx[i] 对所有 i 均落在 [0, i-1] 区间(要求 i >= 1),一遍前向扫描即可由父节点已算出的值递推 prefix[i] = prefix[parent_idx[i]] + node_pnl[i]。用一遍扫描 parent_idx[1:] 维护一个 has_child 布尔数组识别叶节点;答案就是 has_child[v] == False 且 prefix[v] > threshold 的下标 v 的个数。
"严格大于" 这条门是承重的:路径和恰好等于 threshold 的叶节点不计入。当 N = 1 时根本身就是唯一叶节点——若 node_pnl[0] > threshold 返回 1,否则返回 0。当门槛非常负(如 -1e9)时所有叶节点都满足条件,答案退化为整棵树的叶节点总数。
例
solution(
parent_idx = [-1, 0, 0, 1, 1, 2],
node_pnl = [10.0, -5.0, 3.0, -8.0, 2.0, -50.0],
threshold = 0.0
)返回 1。根(index 0)的前缀为 10.0。它的孩子是节点 1 与节点 2:节点 1 的前缀 10 + -5 = 5,节点 2 的前缀 10 + 3 = 13。节点 1 的孩子:节点 3 的前缀 5 + -8 = -3,节点 4 的前缀 5 + 2 = 7。节点 2 的唯一孩子是节点 5,前缀 13 + -50 = -37。叶节点为节点 3、4、5(它们都没有任何孩子),路径和分别为 -3、7、-37,只有节点 4 的 7.0 严格大于 0.0,故计数为 1。根有孩子所以不是叶节点;叶节点的路径和需要逐个与门槛比较——没有任何整树级别的聚合。
朴素的逐叶子重走(每个叶子都从根重算一遍前缀和)最差为 O(N * leaves)(平衡树下退化为二次方);平行数组的前向扫描把每条边均摊一次,为 O(N) 时间、O(N) 空间,配合 N <= 4000 的上限非常宽裕。
实践背景
多期情景树上的定价辅助分析常常需要在期望 PnL 这一聚合量之外,再补一个粗粒度的"赢面计数"描述子:在情景树枚举出的所有终端情景里,到底有多少条的累计 PnL 跨过了某个预设目标(一个 hurdle、一个基准回报、或一个恢复门槛)?期望步告诉你"在叶节点分布上交易台平均能赚多少",而这个计数告诉你"结构上可达的终端结果中,到底有多少条真的越过了门"。它在操作上明显区别于期望步(按分支概率加权)、最差叶报告(坍缩为 min)以及无中间回撤的最深叶(剪掉任何中间前缀跌破零的路径)。同样的平行数组前向扫描可以无变形地推广到生产多结果情景生成器输出的一般(非二叉)情景树上。
约束条件
- 1 <= N <= 4000,其中 N == len(parent_idx) == len(node_pnl);parent_idx[0] = -1 标记根节点。
- 对 i >= 1,parent_idx[i] 在 [0, i-1] 之间(层序属性:父节点必出现在子节点之前)。多个节点可以共享同一个父节点(一般树,不要求是二叉树)。
- 每个 node_pnl[i] 为带符号 float,abs(node_pnl[i]) <= 1e6;node_pnl[0] 为根节点自身的 PnL 贡献。threshold 为带符号 float,abs(threshold) <= 1e9。
- 返回根到叶累计路径和**严格大于** threshold(path-sum > threshold,不是 >=)的叶节点个数(int)。输出为非负 Python int,按精确比对;当没有任何叶节点越过门槛时,合法答案为 0。
- 节点是叶,当且仅当没有其它节点把它列为父亲。N = 1 时根本身就是唯一的叶节点。答案是一个计数值,不是下标列表,不是最大路径和,也不是深度。
样例
Case 1 · statement-example: count leaves above 0.0 = 1
输入: [[-1,0,0,1,1,2],[10,-5,3,-8,2,-50],0]
期望: 1
叶节点为 3/4/5,路径和分别为 -3/7/-37;仅节点 4 的 7.0 严格大于 0.0,计数为 1。
Case 2 · statement-example: equality does not count (strict >)
输入: [[-1,0,0],[5,-2,-2],3]
期望: 0
两个叶节点的路径和都是 5 + -2 = 3.0,等于门槛 3.0;严格大于不成立,计数为 0。
最近提交
还没有提交记录。
编码区
实现 solution(...)。本地运行当前支持 Python 可见样例;服务端提交会运行可见样例和隐藏测试。
默认展示公开样例。点击「运行样例」后会在这里显示实际输出;点击「提交评测」会进入隐藏测试。
Case 1 · statement-example: count leaves above 0.0 = 1
输入: [[-1,0,0,1,1,2],[10,-5,3,-8,2,-50],0]
期望: 1
叶节点为 3/4/5,路径和分别为 -3/7/-37;仅节点 4 的 7.0 严格大于 0.0,计数为 1。
Case 2 · statement-example: equality does not count (strict >)
输入: [[-1,0,0],[5,-2,-2],3]
期望: 0
两个叶节点的路径和都是 5 + -2 = 3.0,等于门槛 3.0;严格大于不成立,计数为 0。