You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CSES子数组和II:CPython3与PyPy3的TLE差异及优化咨询

问题分析与优化方案

你的代码逻辑是正确的——通过前缀和+哈希表统计符合条件的子数组数量,但在CPython3和PyPy3中出现不同测试用例超时的情况,核心原因是哈希表的性能稳定性差异以及IO开销在不同环境下的表现不同。以下是具体分析和优化方向:

为什么会出现跨环境超时?

测试用例规模均为2×10^5,但不同用例的前缀和分布不同:

  • PyPy3超时用例25:大概率是该用例的前缀和几乎全为唯一值,PyPy的字典实现处理大量唯一键时,哈希表扩容、哈希计算的开销比CPython更大,导致超时。
  • CPython3超时用例26、27:这两个用例可能前缀和重复率高,但CPython的IO操作(多次readline)开销累积,加上字典的部分额外开销,最终导致超时。

优化方向与实现

1. 输入读取优化(针对CPython)

CPython的IO性能较弱,多次readline会产生额外系统调用开销。改用一次性读取全部输入的方式,能显著降低IO耗时:

from sys import stdin, stdout

def main():
    data = list(map(int, stdin.read().split()))
    n = data[0]
    x = data[1]
    arr = data[2:2+n]
    
    d = {0: 1}
    curr_sum = 0
    ans = 0
    
    for num in arr:
        curr_sum += num
        ans += d.get(curr_sum - x, 0)
        d[curr_sum] = d.get(curr_sum, 0) + 1
    
    stdout.write(str(ans))

if __name__ == "__main__":
    main()

2. 替换哈希表为二分查找(稳定兼容PyPy/CPython)

哈希表的性能依赖于键的分布,最坏情况可能退化为O(n²)。改用有序前缀和数组+二分查找的方案,能保证O(n log n)的稳定时间复杂度,不受前缀和分布影响:

from sys import stdin, stdout
import bisect

def main():
    data = list(map(int, stdin.read().split()))
    ptr = 0
    n = data[ptr]
    ptr += 1
    x = data[ptr]
    ptr += 1
    arr = data[ptr:ptr+n]
    
    prefix = [0]
    curr_sum = 0
    ans = 0
    
    for num in arr:
        curr_sum += num
        target = curr_sum - x
        # 二分查找目标值的左右边界,计算出现次数
        left = bisect.bisect_left(prefix, target)
        right = bisect.bisect_right(prefix, target)
        ans += right - left
        # 将当前前缀和插入有序数组
        bisect.insort(prefix, curr_sum)
    
    stdout.write(str(ans))

if __name__ == "__main__":
    main()

3. 代码结构优化(针对PyPy)

PyPy对局部变量的访问速度远快于全局变量,将代码包裹在main函数中执行,能减少全局变量的额外开销。

内容的提问来源于stack exchange,提问作者mlp7

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 01:27:58