P3987 我永远喜欢珂朵莉 题解~

\(\text{Preface}\)

前几天做了这道题,讲课就讲了一下,决定来写一篇题解。

我永远喜欢珂朵莉~

有没有大佬教教我怎么卡过 P5610 啊/kk。

\(\text{Description}\)

给定 \(n\) 个数,有如下两个操作:

1 l r x\([l,r]\) 内中 \(x\) 的倍数除以 \(x\)

2 l r 查区间和。

\(1 \le n,m \le 10^5,1\le a_i,x \le 5\times 10^5\)

\(\text{Solution}\)

我们如果将操作变成:对于 \([l,r]\) 的数除以 \(x\)(下取整),那这道题就会非常好做。因为可以证明的是一个数最多除以 \(\log\) 次就可以除到 \(0\),所以直接暴力修改,线段树维护区间和区间最大值即可。

所以我们的问题实际在于如何精准的找出一个区间内 \([l,r]\)\(x\) 的倍数。

这个时候我们回头看一眼空间限制:1.22GB,再看一眼值域: \(x\in [1,500000]\)

我们可以暴力的对每一个数都建一棵平衡树(其结构有点类似于不借助原树结构而直接重新建树的可持久化平衡树)。

这里我使用的是 fhq-treap。

我们先预处理,将每一个 \(a_i\) 的因子所在的平衡树编号中插入 \(i\) 这个位置,在这里推荐用 \(\Theta(n)\) 地建树(毕竟是 lxl 的题),具体怎么建树可以看链接里的代码。

对于操作 \(1\),我们 dfs \(x\) 对应的平衡树,如果某个节点对应的值是 \(x\) 的倍数,就直接暴力修改。同时对于每一个节点检验其是否是 \(x\) 的倍数,如果不是就删除该节点。

但是这里有个问题:既然这个节点在 \(x\) 对应的平衡树里,难道不应该是因为他是 \(x\) 的倍数才可以吗?

其实并不是这样子:假设我先进行区间除以 \(4\),再进行区间除以 \(2\),而在区间除以 \(2\) 的时候有的节点已经被除以 \(4\),可能就不再是 \(2\) 的倍数了,这一步起到了一个特判的作用,同时保证了正确性。

对于操作 \(2\),直接用树状数组统计即可。

细节见代码。

posted @ 2021-04-08 19:27  feicheng  阅读(64)  评论(0编辑  收藏  举报