应用实例:这些结构究竟用在何处
前几页讲的是原理。这一页把它们放进两个可动手体验的真实场景:用树状数组做实时排行榜, 用二维前缀和做图像/热力图的矩形求和(积分图)。每个 demo 都将「换成朴素做法需多少代价」并列对照。
1 · 实时排行榜:查询名次(树状数组)
游戏 / 竞价排名 / 考试系统都要回答「分数 s 排第几名」。名次 = 比我分高的人数 + 1。 朴素做法即便只做有序插入也要
次移动,查名次再扫一遍
。 用树状数组(按分数桶计数):加入是一次 update、查名次是一次前缀和, 都只要
(
为分数上限)。本页分数取 1 到 16,查询至多 4 步、加入至多 5 个节点,榜单再大也不重排。
注 · 名次公式是 ,其中 是总人数、 是分数不超过 的人数(BIT 前缀和), 就是分数比 高的人数。整张榜一个都不用重排。
2 · 积分图:任意矩形区域和 O(1)(二维前缀和)
一张热力图 / 灰度图,反复问「这个矩形框里的总和是多少」(图像模糊的滑窗、人脸检测的 Haar 特征)。 朴素法把框里每个格子加一遍,框越大越慢。二维前缀和(积分图 / summed-area table) 预处理后, 任意矩形和只需查 4 个角、两加两减,与框大小无关——这正是 OpenCV cv::integral() 所做的事。
注 · 容斥公式是 :大矩形减去上、左两条,再把多减的左上角加回来。无论框是 2×2 还是 2000×2000,永远 4 次查表。
3 · 同一思路的其他落点
「预处理出区间聚合 → 把区间问题转化为端点之差 / 树上对数次访问」这一思路,在工程中反复出现:
逆序对计数:衡量序列错乱度 →
从右往左把元素插进权值树状数组,每插一个就 query 比它小的已出现个数——累加就是逆序对数。推荐系统用它衡量「推荐序 vs 实际点击序」错乱度,
取代
暴力。
扫描线:矩形面积并 / 重叠
一条竖线从左扫到右,用线段树 + lazy 维护「当前被覆盖的纵向长度」。EDA 芯片版图 DRC、GIS 地图图层叠加、网页元素碰撞检测都借助它把「众多矩形覆盖了多大面积」计算到 。
批量调价 / 区间生效 →
「把这段时间所有商品涨 10%」「给某区段用户都 +100 积分」——区间整体修改 + 区间查询正是 lazy propagation 的典型用武之地:标记挂在高处,真正读到时才下推,修改一整段也只需 。
报表 / 监控的时间区间统计
「过去 7 天 GMV」「某时间窗错误率峰值」:静态历史用前缀和 取区间;边写边查则采用树状数组 / 线段树,把「实时扫描一段」降为对数级。