跳转至

带短路规则的运算器 — 题解

出题人思路:用可选值保存错误。Codex(GPT-6):完整解析与安全整数求值,以及显式语法树惰性方案。

先确定语法树的形状

用运算符栈把表达式转成后缀记号。按“当前是否需要操作数”区分一元和二元正负号。普通二元运算到来时,弹出优先级更高或相同的旧运算;一元运算右结合,同级时不弹。括号只控制栈边界。

? 先归约更高优先级运算及同级已完成的条件式,再作为分隔标记入栈。读到 : 时,弹出直到匹配的 ?,把它改为待归约的三元运算符。未配冒号的 ? 不参与优先级弹栈。这样,中间分支可包含完整条件式,而后续同级 ? 会先归约前一个已完成条件式。不能照搬 C++ 的右结合规则。

值与错误标志一起求值

后缀栈元素为 (32位值, 是否错误) .数值本身用无符号整数存位模式,比较、除法时先转为有符号 64 位数。四则中的环绕用无符号计算完成,移位先把次数限制到 \(0,\ldots,31\) ,有符号右移由无符号右移和显式符号位掩码实现。对零除数先置错误标志,绝不实际执行非法除法。

普通运算传播任一操作数的错误。逻辑与先检查左值:若左边无错且为零,则返回无错的零,忽略右边错误;逻辑或类似。条件运算先检查条件错误,再仅返回选中分支的值和错误。

这一实现会计算未选中分支的安全错误标志,却不会让它们影响最终结果。其成立依赖本题表达式没有副作用,并且所有危险算术都被安全转换为标志。

正确性

运算符栈的归约顺序满足优先级、括号及规定的结合方向,因此后缀序列对应唯一合法语法树。对树结构归纳:字面量准确;普通运算按规格计算并传播错误;短路节点检查条件后只选择实际所需子结果。因此每个节点的值和可观察错误均与真实短路求值一致,根节点即为答案。

复杂度与贡献

每个记号进出栈常数次,时间和空间均为 \(O(n)\) ,显式栈支持 20 万字符的极深表达式。出题人提出了用可选值保存除零错误的思路;Codex(GPT-6)将其扩展为完整运算符实现,补齐整数语义、左结合条件式和验证。见 std.cpp。

补充方案 建显式语法树,真正跳过未选中的分支。

题面 · 正式数据计划 · 生成器 · 测量记录