洛谷 - P4062 [Code+#1]Yazid 的新生舞会(推公式+线段树)
Posted Frozen_Guardian
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了洛谷 - P4062 [Code+#1]Yazid 的新生舞会(推公式+线段树)相关的知识,希望对你有一定的参考价值。
题目链接:点击查看
题目大意:给出一个长度为 n n n 的序列,现在要求存在 绝对众数 的子区间个数
所谓 绝对众数,就是对于区间 [ l , r ] [l,r] [l,r] 来说,存在一个数字的出现次数 c n t cnt cnt,满足不等式 c n t ∗ 2 > r − l + 1 cnt*2>r-l+1 cnt∗2>r−l+1
题目分析:假如字符集很小,我们可以对每个字符集单独讨论,即枚举每个字符作为众数,判断合法的区间个数。如何判断?设置一个辅助数组 b b b,若原数组的 i i i 位置是该字符,则令 b [ i ] = 1 b[i]=1 b[i]=1,否则 b [ i ] = − 1 b[i]=-1 b[i]=−1,对 b b b 数组维护一个前缀和 s u m sum sum,不难看出区间和严格大于 0 0 0 的区间是合法的区间,即需要寻找合法二元对 ( i , j ) (i,j) (i,j) 的个数满足 s u m [ i ] < s u m [ j ] sum[i]<sum[j] sum[i]<sum[j] 且 i < j i<j i<j。不难看出这就是基于 s u m sum sum 的一个顺序对。可以用树状数组简单维护,时间复杂度 O ( k n l o g n ) O(knlogn) O(knlogn), k k k 为字符集大小。
但是对于本题而言,字符集特别大,和 n n n 同阶,所以考虑优化。
如果对于每个字符都继续沿用上述过程求解的话,我们发现 b b b 数组中绝大部分都是 − 1 -1 −1,且 ∑ 1 = n \\sum1=n ∑1=n
将 b b b 数组中 − 1 -1 −1 特别多的情况自己手玩一下,发现对于前缀和 s u m sum sum 而言,假设 a [ s t ] = a [ e d ] a[st]=a[ed] a[st]=a[ed],且区间 ( s t , e d ) (st,ed) (st,ed) 不再有 a [ i ] = a [ s t ] a[i]=a[st] a[i]=a[st] 的位置 i i i,那么 s u m [ s t : e d ] sum[st:ed] sum[st:ed] 将会是一个公差为 − 1 -1 −1 的等差数列。
我们最终的目的仍然是需要求解“顺序对”的个数,所以线段树一定是跑不了的,考虑如何快速用线段树维护这个等差数列,以及计算这个等差数列的贡献。
回顾计算顺序对最朴素的方法:
- 枚举每个位置 i i i
- a n s + = s u m ( − ∞ : a [ i ] − 1 ] ans+=sum(-\\infty:a[i]-1] ans+=sum(−∞:a[i]−1]
- 将 a [ i ] a[i] a[i] 放进线段树
假设我们需要维护的等差数列, x x x 的坐标为 [ s t , e d ] [st,ed] [st,ed], y y y 对应的区间为 [ L , R ] [L,R] [L,R],更通俗的讲就是, a [ s t ] = R , a [ s t + 1 ] = R − 1 , . . . , a [ e d ] = L a[st]=R,a[st+1]=R-1,...,a[ed]=L a[st]=R,a[st+1]=R−1,...,a[ed]=L
然后我们就很神奇的发现,我们需要维护的这个等差数列,他自己不会提供给自己贡献。具体来说就是,因为对于每个位置 i i i,我们需要统计 s u m ( − ∞ : a [ i ] − 1 ] sum(-\\infty:a[i]-1] sum(−∞:a[i]−1],而这个等差数列 i i i 前面的位置都是大于 a [ i ] a[i] a[i] 的,所以并不会提供贡献
所以根据上述朴素的方法,我们可以得到这个等差数列的贡献为: ∑ i = s t e d ∑ j = − ∞ i − 1 s u m [ j ] \\sum\\limits_{i=st}^{ed}\\sum\\limits_{j=-\\infty}^{i-1}sum[j] i=st∑edj=−∞∑i−1sum[j]
简单推导一下得到:
∑
i
=
L
R
∑
j
=
−
∞
i
−
1
s
u
m
[
j
]
=
∑
i
=
L
R
(
∑
j
=
−
∞
L
−
1
s
u
m
[
j
]
+
∑
j
=
L
i
−
1
s
u
m
[
j
]
)
=
(
R
−
L
+
1
)
∗
∑
j
=
−
∞
L
−
1
s
u
m
[
j
]
+
∑
i
=
L
R
∑
j
=
L
i
−
1
s
u
m
[
j
]
=
(
R
−
L
+
1
)
∗
∑
j
=
−
∞
L
−
1
s
u
m
[
j
]
+
∑
i
=
L
R
(
R
−
i
)
∗
s
u
m
[
i
]
=
(
R
−
L
+
1
)
∗
∑
j
=
−
∞
L
−
1
s
u
m
[
j
]
+
(
R
−
L
+
1
)
∗
R
−
∑
i
=
L
R
i
∗
s
u
m
[
i
]
\\begin{aligned} &\\sum\\limits_{i=L}^{R}\\sum\\limits_{j=-\\infty}^{i-1}sum[j]\\\\ &=\\sum\\limits_{i=L}^{R}(\\sum\\limits_{j=-\\infty}^{L-1}sum[j]+\\sum\\limits_{j=L}^{i-1}sum[j])\\\\ &=(R-L+1)*\\sum\\limits_{j=-\\infty}^{L-1}sum[j]+\\sum\\limits_{i=L}^{R}\\sum\\limits_{j=L}^{i-1}sum[j]\\\\ &=(R-L+1)*\\sum\\limits_{j=-\\infty}^{L-1}sum[j]+\\sum\\limits_{i=L}^{R}(R-i)*sum[i]\\\\ &=(R-L+1)*\\sum\\limits_{j=-\\infty}^{L-1}sum[j]+(R-L+1)*R-\\sum\\limits_{i=L}^{R}i*sum[i] \\end{aligned}
i=L∑Rj=−∞∑i−1sum[j]=i=L∑R(j=−∞∑L−1sum[j]+j=L∑i−1sum[j])=(R−L+1)∗j=−∞∑L−1sum[j]+i=L∑Rj=L∑i−1sum[j]=(R−L+1)∗j=−∞∑L−1sum[j]+i=LP4062 [Code+#1]Yazid 的新生舞会(线段树做法)
luogu P4062 [Code+#1]Yazid 的新生舞会(线段树+套路)
BZOJ5110[CodePlus2017]Yazid 的新生舞会 线段树