Loading

序列

https://xinyoudui.com/ac/contest/74500D4AE000A6307E7138/problem/43753

签到在哪?简单在哪?

原本我的二维线段树也就是 KDT 维护平面标记大概能做到一个 \(O(n polylog(n) polylog(V))\),不是很能优化。

首先解释做法的基本原理,枚举每个区间,从小到大加数,如果当前数减 \(1\) 大于等于之前所有数的和,此时区间答案就是之前所有数的和,然后停止这个过程,通过值域平移的手段不能证明这个是正确的。

考察一个关键的优化在于,对于每个区间值域倍增分块成 \([2^k, 2^{k + 1})\),此时有结论,上述可能取到的停止位置的数只有可能是每一个块中最小的那个数,因为如果不是最小的那个数,之前所有数的和加上该块最小数已经足以跳到下一个块,证毕。

此时枚举枚举块 \([2^k, 2^{k + 1})\),对于每个右端点 \(r\),考察其最左能够取到的左端点 \(l\),使得 \([l, r]\) 这个区间能够满足前 \(k\) 个块的和小于后面的块的最小值,不难发现该问题具有单调性,随着 \(r\) 的增加,\(l\) 也会增加,可以用一个双指针维护单调队列和前缀和做这个过程。

注意到对于 \(r\),其每一个对应左端点 \(l \le l' \le r\),区间 \([l', r]\) 的答案都不会超过前 \(k\) 个数的和,我们考虑再次维护一个指针从而恰好描述能够取到前 \(k - 1\) 个块所对应的区间的左端点最左是哪里,那么中间的部分就是恰好取到前 \(k - 1\) 的和了,此时用一个前缀和数组记录每个 \(a_i\) 被统计入多少次答案即可,差分完后滚两边前缀和即可。

posted @ 2026-01-26 19:14  Alexande  阅读(0)  评论(0)    收藏  举报