传送门:P8353 [SDOI/SXOI2022] 无处存储
免责声明:我不是本题的出题人。
出题人是小N和小 Ω \Omega Ω ,跟我小Z有什么关系?
题目大意:给定一棵树,点有点权,支持链加、链求和。强制在线。
(先别急着说“为什么省选放模板题”,接着往下看。)
数据范围: n ≤ 7 × 1 0 6 , q ≤ 5 × 1 0 4 n \leq 7\times10^6,q\leq 5\times 10^4 n≤7×106,q≤5×104。
时空限制: 5 s , 64 M B 5s,\ 64MB 5s, 64MB 。
——是的你没看错,卡空间题!更准确地说,跟一些比较屑的、卡一些实现不优秀正解的空间常数的相比,这题是一个纯纯的需要你设计算法来卡空间的题!
——对此,我的评价是:

也难怪出题人对自己题目的评价是:

“出题人爬!”
“为什么要喷自己?”
“如果我主动喷自己的话,就没有选手来喷我了吧(大概吧”
我们冷静分析一下这个数据范围和空间限制意味着什么:
一个大小为 n = 7 × 1 0 6 n=7\times 10^6 n=7×106 的int数组需要大约 26.7 M B 26.7MB 26.7MB 的空间,也就是说最多只能开 2 2 2 个。
显然需要一个数组存所有的点权,另外需要一个数组存每个点在树上的父亲。
然后就没了,你没法开下任何 O ( n ) O(n) O(n) 级别的数据结构,甚至没法直接dfs整棵树,因为栈空间也要算在内。
——那还玩个啥?只能暴力了?
冷静分析:其实 64 M B 64MB 64MB 的限制没有想象中那么死,大概还留下接近 10 M B 10MB 10MB 来给我们开一些 o ( n ) o(n) o(n) 的小数组,比如 O ( n ) O(\sqrt n) O(n) 甚至 O ( n / log n ) O(n/\log n) O(n/logn) 的数组还是能开的,包括 n / 32 n/32 n/32 的bitset(每个不到 1 M B 1MB 1MB)也可以开好几个。
如果你还在想 log \log log 做法,可以就此打住了。据我所知,空间最小的 log \log log 做法应该是树剖+树状数组,即使考虑到人工栈dfs+数组复用, 4 n 4n 4n 的空间是避免不了的。由此可以大胆猜测这一定是个根号题,而看到这个数据范围不难猜应该是 O ( q n ) O(q\sqrt n) O(qn) 一类的算法。
当然你也许会想到一些奇技淫巧的卡空间技巧,比如:考虑到fa数组只有低 24 24 24 位是有用的,或许可以强行用 3 3 3 个int存储 4 4 4 个数。但遗憾的是,即使你将此方法运用到极致,也刚好无法开下第 3 3 3 个 O ( n ) O(n) O(n) 的数组(需要至少 65 M B 65MB 65MB )。不过放心,以下的 2 2 2 个数组解法完全无需依赖这一卡空间方法。
我们姑且先弱化问题。序列上怎么做?这还用说?树状数组只需要2n的空间。
众所周知的一种分块方法是:每个单点维护(不含标记的)权值,每个块内维护这个块的和,以及这个块的整体加标记。修改时整块打标记,零散暴力;查询时整块直接查,零散暴力。时间复杂度 O ( q n ) O(q\sqrt n) O(qn) ,空间 n + O ( n ) n + O(\sqrt n) n+O(n) (只需要开一个 O ( n ) O(n) O(n) 的数组)。
放到树上呢?当然是树分块了!这个名词听起来就相当哈人,这里推荐一种相对好写的树分块写法:
在树上随机撒 O ( n ) O(\sqrt n) O(n

本文探讨了一道省选竞赛中的题目,该题目要求在极端的空间限制下(64MB内存)解决一棵树上的链加、链求和问题。通过分析数据范围和空间限制,作者提出了一种基于树分块的算法,该算法具有O(qn)的时间复杂度和约55~58MB的实际空间占用。算法涉及随机撒关键点、树状数组和位运算等技术,展现了在空间受限条件下设计高效算法的思路。
最低0.47元/天 解锁文章
479

被折叠的 条评论
为什么被折叠?



