CodeForces 1098E. Fedya the Potter

题目简述:给定长度为$n leq 5 imes 10^4$的序列$a_1, a_2, dots, a_n leq 10^5$。将$gcd(a_l, a_{l+1}, dots, a_r) (1 leq l leq r leq n) $从小到大排序后得到长度为$n(n+1)/2$的序列$b$。将$b_l+b_{l+1}+dots+b_r (1 leq l leq r leq n(n+1)/2)$从小到大排序后得到序列$c$。求$c$的中位数。

注:若$c$的下标从$1$开始,则$c$的中位数定义为其第$lfloor (k+1)/2 floor$个元素。

解:

code

这题可分成明显的几个步骤。

Step 1:统计不同的$gcd$

相关题目:[NOI2012]魔幻棋盘

固定$i$,令$g(j) = gcd{a_i, a_{i+1}, dots, a_j} (1 leq i leq j leq n)$,则$g(j) | a_i$且$g(j)$单调递减,从而不相同的$g(j)$的个数$= O(log a_i)$。于是序列$b$中互不相同的元素个数只有$O(n log V)$,其中$V = max_i {a_i}$为序列$a$的最大值。

根据$g(j)$的单调性,可以通过二分法依次求出所有不同的$g(j)$及其个数。

为了能在二分时对任意$1 leq l leq r leq n$,快速计算出$gcd(a_l, a_{l+1}, dots, a_r)$,我们需要用倍增思想预处理出$d[i][k] = gcd (a_i, a_{i+1}, dots, a_{i+2^k-1})$,其递推式为

$$ d[i][k] = gcd(d[i][k-1], d[i+2^{k-1}][k-1]). $$

预处理$d[i][k]$时间复杂度为$O(n log n log V)$。对某个$i$,统计出所有不同的$g(j)$及其个数,需要至多使用二分法$O(log V)$次,二分法需要二分$O(log n)$步,每步需要计算$gcd$的复杂度为$O(log V)$,故总时间复杂度为$O(n log n log^2 V)$。

Step 2:二分$c$的中位数

相关题目:AtCoder Regular Contest 101 D. Median of Medians

使用二分法求$c$的中位数$m$,于是问题转化为统计$c$中$geq x$的数的个数$t$。由于$c$中元素个数为$N(N+1)/2$,其中$N = n(n+1)/2$,若$t geq lfloor (N+1)/2 floor$,则说明$x geq m$,否则$x < m$。二分法的上界是需要估计一下的,最坏情况$a_1 = a_2 = dots = a_n = V$,这时$b_i = V$,$c$的最大值为$V n(n+1)/2 < 1.3 imes 10^{14}$。故需要$O(log (Vn(n+1)/2) ) = O(log V + log n)$步。

记$b[v]$表示$v$在$b$中出现的次数,$b[l dots r]$表示$l dots r$在$b$中出现的次数,以及

$$ S[v] = sum_{k=1}^v k b[k] $$

表示所有$leq v$的元素之和,简记$S[l dots r] = S[l]+dots+S[r]$。

对给定的$x$,我们枚举$i$,计算以$i$为最大元素的$b_l+b_{l+1}+dots+b_r leq x$求和的个数,简称为$b$求和(我们把$c$中的一个元素成为一个$b$求和)。

1. 若$S[i] leq x$,则任意一个以$i$为最大元素的$b_l+b_{l+1}+dots+b_r$求和均$leq x$,故满足条件的$b$求和个数为

$$ sum_{k=1}^{b[i]} (b[1 dots i-1]+k) = b[i] b[1dots i-1]+frac 1 2 b[i] (b[i]+1). $$

2. 若$S[i] > x$,枚举$i$出现的次数$1 leq l leq b[i]$,找到最小的$j < i$,使得$S[j+1 dots i-1]+li leq x$,则以$i$为最大元素且个数至少为$l$,$j$为最小元素的$b$求和个数为

$$ sum_{k=l}^{b[i]} max left{ min left{ leftlfloor frac {x-S[j+1 dots i-1]-ki} {j} ight floor, b[j] ight} , 0 ight}. $$

我们只需考虑$x-S[j+1 dots i-1]-ki > 0$的情况,即$k<(x-S[j+1 dots i-1])/i$。令$r = minleft{ b[i], leftlfloor (x-S[j+1 dots i-1])/ i ight floor ight}$,从而以上求和化为

$$ sum_{k=l}^{r} min left{ leftlfloor frac {x-S[j+1 dots i-1]-ki} {j} ight floor, b[j] ight}. $$

此式可化为

$$ sum_{k=l}^r leftlfloor frac {x-S[j+1 dots i-1]-ki} {j} ight floor - sum_{k=l}^r max left{ leftlfloor frac {x-S[j+1 dots i-1]-ki} {j} ight floor - b[j], 0 ight} $$

$$ sum_{k=0}^{r-l} leftlfloor frac {x-S[j+1 dots i-1]-li-ki} {j} ight floor - sum_{k=0}^{r-l} max left{ leftlfloor frac {x-S[j+1 dots i-1]-li-ki-jb[j]} {j} ight floor , 0 ight} $$

化简为

$$ f(-i, x-S[j+1 dots i-1]-li, j, r-l) - f(-i, x-S[j+1 dots i-1]-li-jb[j], j, r-l), $$

其中

$$ f(a,b,c,n) = sum_{k=0}^n max left{ leftlfloor frac {ak+b} {c} ight floor, 0 ight}. $$

特别地,若不存在$j < i$,使得$S[j+1 dots i-1]+li leq x$,则以$i$为最大元素且至少有$l$个的$b$求和个数为

$$ sum_{k=l}^{b[i]} min left{ k, leftlfloor frac x i ight floor ight}. $$

Step 3: 计算$f(a, b, c, n)$

我们需要把$f(a,b,c,n)$转化为$a, b, c, n geq 0$的情形。

若$n < 0$,则$f(a,b,c,n) = 0$。

若$c < 0$,可利用$f(a,b,c,n) = f(-a, -b, -c, n)$使得$c > 0$。

若$c > 0$但$a < 0$,可利用$f(a,b,c,n) = f(-a,b+an,c,n)$使得$c > 0$且$a > 0$。

若$c > 0, a > 0$但$b < 0$,可利用$f(a,b,c,n) = f(a, b+lceil -b/a ceil a, c, n-lceil -b/a ceil)$使得$a, b, c > 0$。

当$a, b, c > 0$时,$f(a,b,c,n)$可化为范式

$$ f(a,b,c,n) = sum_{k=0}^n leftlfloor frac {ak+b} {c} ight floor. $$

我们用Euclid算法计算$f(a,b,c,n)$。

1. 若$n = 0$,则$f(a,b,c,n) = lfloor b/c floor (n+1)$。

2. 若$a geq c$或$b geq c$,令$a = lfloor a/c floor c+a', b = lfloor b/c floor c+b'$,则

$$ f(a,b,c,n) = sum_{k=0}^n leftlfloor frac {(lfloor a/c floor c+a')k+(lfloor b/c floor c+b')} {c} ight floor = f(a', b', c, n)+frac 1 2 n(n+1) leftlfloor frac {a} {c} ight floor + (n+1) leftlfloor frac {b} {c} ight floor. $$

3. 若$a,b < c$,令$m = leftlfloor frac {an+b} {c} ight floor$,则

$$ egin{aligned} f(a,b,c,n) & = sum_{k=1}^n leftlfloor frac {ak+b} {c} ight floor \ & = sum_{x=1}^n sum_{y=1}^m left[ frac {ax+b} {c} leq y ight] \ & = sum_{y=1}^m sum_{x=1}^n left[ frac {cy-b} {a} geq x ight] \ & = nm-sum_{y=1}^m sum_{x=1}^n left[ frac {cy-b} {a} < x ight] \ & = nm-sum_{y=1}^m left( leftlfloor frac {cy-b} {a} ight floor - [a|(cy-b)] ight) \ & = nm-sum_{y=1}^m leftlfloor frac {cy-b-1} {a} ight floor \ & = nm-sum_{y=0}^{m-1} leftlfloor frac {cy+c-b-1} {a} ight floor \ & = nm-f(c, c-b-1, a, m-1) end{aligned} $$

Euclid辗转相除法的时间复杂度为$O(log min { a, b })$。

算法总时间复杂度为$O(n log n log^2 V + V log V (log n+log V))$。

原文地址:https://www.cnblogs.com/TinyWong/p/10355779.html