• 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))$。

  • 相关阅读:
    07ES6 模板字符串
    Python: Factory Method Pattern
    CSharp: Singleton Pattern in donet core 3
    CSharp: Decorator Pattern in donet core 3
    CSharp: Visitor Pattern in donet core 3
    CSharp: Observer Pattern in donet core 3
    CSharp: Flyweight Pattern in donet core 3
    CSharp: Adapter Pattern in donet core 3
    CSharp: Composite Pattern in donet core 3
    CSharp: Facade Pattern in donet core 3
  • 原文地址:https://www.cnblogs.com/TinyWong/p/10355779.html
Copyright © 2020-2023  润新知