牛客练习赛100 小红的公倍数【ODT】
题目描述
link: https://ac.nowcoder.com/acm/contest/11251/E
小红拿到了一个数组,她有以下一种操作:
将[l,r]区间所有数变成该区间所有数的lcm,并输出这个lcm。
一共q次操作。
1
≤
n
,
q
,
a
[
i
]
≤
20000
1\le n,q,a[i] \le 20000
1≤n,q,a[i]≤20000,数据随机生成。
题目分析
期末考前随手打一场玩一玩,结果这题写WA了,属于是退役Oier不配打比赛了
比赛结束看了看AC代码,我只能说随机出人才ヽ(≧□≦)ノ
看到 这份代码,用的莫队,但是有个以前没见过的 trick:
因为这题操作会把所有数变成同一个,所以在
t
t
t 时刻的
[
l
,
r
]
[l,r]
[l,r] 操作,它要求的答案实际上是一个更大区间的 lcm,如果要用莫队做的话就要把每一个操作对应的这个“更大的区间”给预处理出来。这个预处理要用ODT,每个节点存四个数,分别是 “操作区间的左右端点” 和 “与lcm有关系的历史区间的左右端点”,具体方法参见链接代码。
预处理结束后问题就变成去除重新赋值的影响后求区间lcm,用莫队做的话,要维护区间每个质因子的数量,用个multiset num[N],每个
a
[
i
]
a[i]
a[i] 对应的不同质因子及对应数量都要记下来,才能在添加和删除的时候通过 gcd 的变化维护 lcm。
复杂度大概是
O
(
n
n
log
n
∗
C
)
O(n\sqrt n \log n*C)
O(nnlogn∗C),
C
C
C 是每个数的不同质因子个数,平均只有3,4
这个做法比较靠谱,不依赖数据随机。
另外还有一个比较暴力的方法,就是 ODT 直接做,每个节点用 unordered_map 存质因子对应个数,合并直接遍历 map。当然要加一些显然的优化,比如区间被覆盖时直接返回结果。复杂度玄学,用时 2s。参见 这份代码
还有一些其它利用随机性质的做法。有兴趣的可以到提交代码区看看。