题目大意 规定线段树上 [ l , r ] [l,r] [ l , r ] 这个区间往下分会分到 [ l , ⌊ l + r 2 ⌋ ] [l,\lfloor \frac{l+r}2 \rfloor] [ l , ⌊ 2 l + r ⌋] 、[ ⌊ l + r 2 ⌋ + 1 , r ] [\lfloor \frac{l+r}2 \rfloor+1,r] [⌊ 2 l + r ⌋ + 1 , r ] ,直到区间长度为 1 1 1 为止。 设 f ( i , n ) f(i,n) f ( i , n ) 为 [ i , i ] [i,i] [ i , i ] 这个区间在有 n n n 个叶子的线段树上的深度(根节点深度为 1 1 1 ),求:
∑ n = L R ∑ i = 1 n f ( i , n ) × i \sum_{n=L}^R \sum_{i=1}^n f(i,n) \times i n = L ∑ R i = 1 ∑ n f ( i , n ) × i
L , R ≤ 5 × 10 17 L,R \leq 5 \times 10^{17} L , R ≤ 5 × 1 0 17
题解 设 f n f_n f n 表示有 n n n 个叶子的线段树的叶子深度和,g n g_n g n 表示 叶子深度乘叶子 id 的和,h n h_n h n 表示 叶子深度乘 n n n 的和,设 F n F_n F n 、G n G_n G n 、H n H_n H n 分别为它们的前缀和。
答案就是 G R − G L − 1 G_R-G_{L-1} G R − G L − 1 ,F F F 和 H H H 算是辅助函数。
考虑怎么递推求 F n F_n F n ,这里一共是 n n n 棵线段树,每一棵都分一半,分成这样:
[ 1 , 1 ] : [ 1 , 1 ] [ 1 , 2 ] : [ 1 , 1 ] + [ 2 , 2 ] [ 1 , 3 ] : [ 1 , 2 ] + [ 3 , 3 ] [ 1 , 4 ] : [ 1 , 2 ] + [ 3 , 4 ] [ 1 , 5 ] : [ 1 , 3 ] + [ 4 , 5 ] [ 1 , 6 ] : [ 1 , 3 ] + [ 4 , 6 ] [ 1 , 7 ] : [ 1 , 4 ] + [ 5 , 7 ] ⋮ \begin{aligned} [1,1]&:~~[1,1] \\ [1,2]&:~~[1,1]+[2,2] \\ [1,3]&:~~[1,2]+[3,3] \\ [1,4]&:~~[1,2]+[3,4] \\ [1,5]&:~~[1,3]+[4,5] \\ [1,6]&:~~[1,3]+[4,6] \\ [1,7]&:~~[1,4]+[5,7] \\ &\vdots \end{aligned} [ 1 , 1 ] [ 1 , 2 ] [ 1 , 3 ] [ 1 , 4 ] [ 1 , 5 ] [ 1 , 6 ] [ 1 , 7 ] : [ 1 , 1 ] : [ 1 , 1 ] + [ 2 , 2 ] : [ 1 , 2 ] + [ 3 , 3 ] : [ 1 , 2 ] + [ 3 , 4 ] : [ 1 , 3 ] + [ 4 , 5 ] : [ 1 , 3 ] + [ 4 , 6 ] : [ 1 , 4 ] + [ 5 , 7 ] ⋮
这是 n n n 为奇数的情况,可以发现,左边分为了两组前缀和:F ⌊ n 2 ⌋ F_{\lfloor \frac n2 \rfloor} F ⌊ 2 n ⌋ 和 F ⌈ n 2 ⌉ F_{\lceil \frac n2 \rceil} F ⌈ 2 n ⌉ (偶数下标对应第一组,奇数下标对应第二组,每一组的区间长度恰好是 1 , 2 , 3 , ⋯ 1,2,3,\cdots 1 , 2 , 3 , ⋯ ,所以是分成两组前缀和),右边也分为了两组前缀和:都是 F ⌊ n 2 ⌋ F_{\lfloor \frac n2 \rfloor} F ⌊ 2 n ⌋ (偶数下标对应第一组,奇数下标对应第二组)。 然后还要考虑左右子树拼起来之后,除第一棵树外所有叶子的深度都加了 1 1 1 ,因此 n n n 棵树增加的深度和就是 2 + 3 + ⋯ + n = n ( n + 1 ) 2 − 1 2+3+\cdots+n=\frac{n(n+1)}{2}-1 2 + 3 + ⋯ + n = 2 n ( n + 1 ) − 1 。 因此 n n n 为奇数时的 F F F 的递推式出来了:
F n = 3 ⋅ F ⌊ n 2 ⌋ + F ⌈ n 2 ⌉ + n ( n + 1 ) 2 − 1 , n i s o d d F_n=3 \cdot F_{\lfloor \frac n2 \rfloor}+F_{\lceil \frac n2 \rceil}+\frac{n(n+1)}{2}-1~~~~~~,n~is~odd F n = 3 ⋅ F ⌊ 2 n ⌋ + F ⌈ 2 n ⌉ + 2 n ( n + 1 ) − 1 , n i s o dd
n n n 为偶数是类似的,左边分成的两组都是 F n 2 F_{\frac n2} F 2 n ,右边的两组分别为 F n 2 F_{\frac n2} F 2 n 和 F n 2 − 1 F_{\frac n2 -1} F 2 n − 1 :
F n = 3 ⋅ F n 2 + F n 2 − 1 + n ( n + 1 ) 2 − 1 , n i s e v e n F_n=3 \cdot F_{\frac n2}+F_{\frac n2 -1}+\frac{n(n+1)}{2}-1~~~~~~,n~is~even F n = 3 ⋅ F 2 n + F 2 n − 1 + 2 n ( n + 1 ) − 1 , n i s e v e n
接下来推 H n H_n H n ,也是同样的思路,左边右边各分成两组。以 n n n 为奇数时左边两组为例,因为 h i = ∑ d e e p x ⋅ i h_i=\sum deep_x \cdot i h i = ∑ d ee p x ⋅ i ,先考虑把 i i i 变对,那么其中一组是要把 i i i 变成 2 i − 1 2i-1 2 i − 1 ,另一组要把 i i i 变成 2 i 2i 2 i ,因此对应的分别是 2 H ⌈ n 2 ⌉ − F ⌈ n 2 ⌉ 2H_{\lceil \frac n2 \rceil}-F_{\lceil \frac n2 \rceil} 2 H ⌈ 2 n ⌉ − F ⌈ 2 n ⌉ 和 2 H ⌊ n 2 ⌋ 2H_{\lfloor \frac n2 \rfloor} 2 H ⌊ 2 n ⌋ 。 然后考虑左右子树拼起来后增加的深度的贡献,区间长度为 i i i 的树有 i i i 个叶子,每个叶子贡献增加 i i i ,那么是 2 2 + 3 2 + 4 2 + ⋯ + n 2 = n ( n + 1 ) ( 2 n + 1 ) 6 − 1 2^2+3^2+4^2+\cdots+n^2=\frac{n(n+1)(2n+1)}6-1 2 2 + 3 2 + 4 2 + ⋯ + n 2 = 6 n ( n + 1 ) ( 2 n + 1 ) − 1 。 因此递推式为:
H n = ( 2 H ⌈ n 2 ⌉ − F ⌈ n 2 ⌉ ) + ( 2 H ⌊ n 2 ⌋ ) + ( 2 H ⌊ n 2 ⌋ + F ⌊ n 2 ⌋ ) + ( 2 H ⌊ n 2 ⌋ ) + n ( n + 1 ) ( 2 n + 1 ) 6 − 1 , n i s o d d H_n=(2H_{\lceil \frac n2 \rceil}-F_{\lceil \frac n2 \rceil})+(2H_{\lfloor \frac n2 \rfloor})+(2H_{\lfloor \frac n2 \rfloor}+F_{\lfloor \frac n2 \rfloor})+(2H_{\lfloor \frac n2 \rfloor})+\frac{n(n+1)(2n+1)}6-1~~~~~~,n~is~odd \\ H n = ( 2 H ⌈ 2 n ⌉ − F ⌈ 2 n ⌉ ) + ( 2 H ⌊ 2 n ⌋ ) + ( 2 H ⌊ 2 n ⌋ + F ⌊ 2 n ⌋ ) + ( 2 H ⌊ 2 n ⌋ ) + 6 n ( n + 1 ) ( 2 n + 1 ) − 1 , n i s o dd
偶数就不写了。
接下来推 G N G_N G N ,还是一样的,要考虑的就是右子树的起始下标被左子树抬上去了,所以这部分是用 H H H 函数来做贡献:
G n = G ⌈ n 2 ⌉ + G ⌊ n 2 ⌋ + ( G ⌊ n 2 ⌋ + H ⌊ n 2 ⌋ ) + ( G ⌊ n 2 ⌋ + H ⌊ n 2 ⌋ + F ⌊ n 2 ⌋ ) + ∑ i = 2 n i ( i + 1 ) 2 , n i s o d d G_n=G_{\lceil \frac n2 \rceil}+G_{\lfloor \frac n2 \rfloor}+(G_{\lfloor \frac n2 \rfloor}+H_{\lfloor \frac n2 \rfloor})+(G_{\lfloor \frac n2 \rfloor}+H_{\lfloor \frac n2 \rfloor}+F_{\lfloor \frac n2 \rfloor})+\sum_{i=2}^n \frac{i(i+1)}{2}~~~~~~,n~is~odd G n = G ⌈ 2 n ⌉ + G ⌊ 2 n ⌋ + ( G ⌊ 2 n ⌋ + H ⌊ 2 n ⌋ ) + ( G ⌊ 2 n ⌋ + H ⌊ 2 n ⌋ + F ⌊ 2 n ⌋ ) + i = 2 ∑ n 2 i ( i + 1 ) , n i s o dd
偶数就不写了。
最后来分析时间复杂度,n n n 为奇数时递归到 ⌈ n 2 ⌉ \lceil \frac n2 \rceil ⌈ 2 n ⌉ 和 ⌊ n 2 ⌋ \lfloor \frac n2 \rfloor ⌊ 2 n ⌋ ,n n n 为偶数时递归到 n 2 \frac n2 2 n 和 n 2 − 1 \frac n2 -1 2 n − 1 ,可以观察到,每往下走一层都是一段连续的区间,比如 n = 32 n=32 n = 32 ,往下走到 15 15 15 和 16 16 16 ,再往下走到 7 , 8 , 9 7,8,9 7 , 8 , 9 ,再往下走到 3 , 4 , 5 3,4,5 3 , 4 , 5 …… 因为同一层相邻的两个数,往下走是会交的,因此每一层最多比上一层多一个数,因此总量是 O ( log 2 n ) O(\log^2 n) O ( log 2 n ) 的。
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 #include <bits/stdc++.h> #define fo(i,a,b) for(int i=a;i<=b;i++) using namespace std ; typedef long long LL;const LL mo=998244353 ;LL L,R,inv2,inv6; LL mi (LL x,LL y) { LL re=1 ; for (; y; y>>=1 , x=x*x%mo) if (y&1 ) re=re*x%mo; return re; } map <LL,LL> f,g,h; LL sum (LL n) { n%=mo; return n*(n+1 )%mo*inv2%mo; } LL sum2 (LL n) { n%=mo; return n*(n+1 )%mo*(2 *n+1 )%mo*inv6%mo; } LL sums (LL n) { return (sum2(n)+sum(n))%mo*inv2%mo; } void dfs (LL n) { if (f.count(n)) return ; if (n<=1 ) { f[n]=g[n]=h[n]=n; return ; } if (n&1 ) { LL l=(n+1 )>>1 , r=n>>1 ; dfs(l), dfs(r); f[n]=(f[l]+f[r]*3 +sum(n)-1 +mo)%mo; g[n]=(g[l]+g[r]+(g[r]+h[r])+(g[r]+h[r]+f[r])+mo+sums(n)-1 +mo)%mo; h[n]=(h[l]*2 -f[l]+h[r]*2 +h[r]*2 +f[r]+h[r]*2 +sum2(n)-1 +mo)%mo; } else { LL l=n>>1 , r=l-1 ; dfs(l), dfs(r); f[n]=(f[l]*3 +f[r]+sum(n)-1 +mo)%mo; g[n]=(g[l]*2 +(g[l]+h[l])+(g[r]+h[r]+f[r])+mo+sums(n)-1 +mo)%mo; h[n]=(h[l]*2 -f[l]+h[l]*2 +h[l]*2 +h[r]*2 +f[r]+sum2(n)-1 +mo)%mo; } } LL calc (LL n) { dfs(n); return g[n]; } int T;int main () { inv2=mi(2 ,mo-2 ); inv6=mi(6 ,mo-2 ); scanf ("%d" ,&T); while (T--) { scanf ("%lld %lld" ,&L,&R); printf ("%lld\n" ,(calc(R)-calc(L-1 )+mo*2 )%mo); } }