【学习笔记】「UNR #5」诡异操作
在优秀的学长 C202044zxy 讲解下把这道题搞懂了。希望自己也有机会成为学长。
原来线段树还可以这样干!考虑线段树上每个节点用一个数组维护 2 i 2^i 2i的出现次数,也就是二进制下某一位为 1 1 1的数目。这样只看操作一,每个点最多要修改 log V \log V logV次,但是线段树上合并左右儿子也有一个 log V \log V logV的复杂度,复杂度算上去好像是 O ( n log n log 2 V ) O(n\log n\log^2 V) O(nlognlog2V)。
然后有一个很厉害的 trick \text{trick} trick。考虑之前我们每个节点维护的是权值为 2 i 2^i 2i的数出现的次数,现在我们改成维护出现次数为 2 i 2^i 2i的权值的集合,总之我们构造了一个 log n × log V \log n\times \log V logn×logV的 01 01 01矩阵,把每行拿来维护,发现合并的时候就按行从下往上合并就好了。这个时候复杂度发生了微妙的变化:
1.1
1.1
1.1 每次合并的复杂度从
log
V
\log V
logV变成了
log
n
\log n
logn。
1.2
1.2
1.2 设这个区间长度为
l
e
n
len
len,那么只有
2
i
≤
l
e
n
2^i\le len
2i≤len的行才会有值。
现在我们用另一种方法再来算一次复杂度。我们分成普通操作和特殊操作,其中普通操作包括将每个修改区间分成若干个完整的线段树上的区间,并向上合并,这部分复杂度 O ( n log 2 n ) O(n\log^2n) O(nlog2n);特殊操作包括对每个完整的区间进行修改(区间所有数除以 v v v),注意到每个点最多被修改 log V \log V logV次就会全部变成 0 0 0,并且其合并复杂度应该是 log l e n \log len loglen,让计算工具帮我们算一下发现 T ( n ) = 2 T ( n 2 ) + O ( log n ) = O ( n ) T(n)=2T(\frac{n}{2})+O(\log n)=O(n) T(n)=2T(2n)+O(logn)=O(n),这样总复杂度 O ( n log 2 n + n log V ) O(n\log ^2n+n\log V) O(nlog2n+nlogV)就对了。当然我们只是分析了操作一的复杂度,其实操作二的复杂度也是对的,这个可以自己验证。
写了一发,发现之前复杂度之所以算错是因为 操作二的复杂度不需要借助势能来分析,因此从某方面来说操作一和操作二的复杂度计算(或者说操作次数)是独立的。kid_magic 早已意识到了这点,或许这就是神的直觉吧。
这题怎么卡常啊。
用内存池来实现,这样可以把空间优化到 O ( n ) O(n) O(n)。这一点确实比较难想到。
__EOF__

本文链接:https://www.cnblogs.com/cqbzly/p/17529944.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是博主的最大动力!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
2022-07-04 【学习笔记】图的连通性与回路
2022-07-04 【简要题解】OI Online能力测试校内赛(Round One)T2~T4
2022-07-04 【学习笔记】阶段测试1