题面
现有 n
个整数 a1,a2,…,an
,并且有 m
次查询。每次查询时需对给定的 p
计算下面表达式的值:
1≤i≤n∑⌊⌈logpai⌉ai⌋
数据范围:
1≤n,m≤5×105
2≤ai,pi≤109
题目链接
分析
我们注意到,⌈logpai⌉
的取值在题目的取值范围下其实非常有限:
⌈logpai⌉∈[1,31]
也就是说,对于同一个 p
,⌈logpai⌉
的值很可能对于多个 ai
是相等的。
另外我们注意到 logpai
是单调递增的。如果我们先对这 n
个整数从小到大排序,那么对于排序后的数列,我们可以将其划分为若干个连续区间,使得每个区间内 ⌈logpai⌉
的值都相等。那么我们不妨将排序后的数组连续地划分成 31
个区间(区间可以包含 0
个元素),使得每个区间内所有 ai
的 ⌈logpai⌉
都相等。如果我们能够快速地求出每个区间的区间和加起来,这样复杂度就能降低不少。
既然 ⌈logpai⌉
的取值情况很少,我们可以考虑预处理所有的 kai (k∈Z,k∈[1,31])
。同时在预处理的时候,我们可以将其处理为前缀和的形式,这样我们就可以以 O(1)
的复杂度求出上面提到的每个区间的区间和。
至于区间具体如何划分,我们不妨借助二分查找。第 k
个区间的第一个元素也就是原数组中第一个大于 pk
的元素。
这样一来,预处理的复杂度为 O(n)
,m
次查询的复杂度为 O(mlogn)
,而常数则为 31
。
实现
完整参考代码