P4062 - Yazid 的新生舞会 题解

Portal

首先考虑用众数而非区间来贡献答案。我们考虑对每个数都处理出它所在的位置 list,然后对每个 list 独立搞。

一个简单粗暴的想法是,列出两个位置构成的区间满足条件的充要条件,然后发现是一个关于 \(i\) 的式子和关于 \(j\) 的式子的不等式,BIT 维护一下就行了,但这样每个是 \(\mathrm O(n\log)\),最坏能被卡到 \(\Omega\!\left(n^2\right)\)。于是我们要努力让复杂度不关于 \(n\),只关于当前数的个数。

于是我们一步步来把 \(n\) 给去掉。首先肯定不能枚举右端点 \(j\) 了。设当前数的位置 list 为 \(a\)。于是我们考虑枚举 \(a_j\sim a_{j+1}-1\) 的这个 gap,这样至少枚举量不关于 \(n\) 了。我们看对于左端点 \(i\),它右边第一个为 \(a_i'\),那么它与 \(j\) 的共同贡献,就看一下它至少要伸多远,和 \(a_{j+1}-1\) 取个 \(\min\),然后算一下到 \(a_j\) 的距离与 \(0\) 取个 \(\max\)。式子列出来:

\[\max\!\left(0,\min\!\left(a_{j+1}-1,a_i'+2(j-i+1)-1-1\right)-a_j+1\right) \]

比较长的那串整理一下是 \(a_i'+2j-2i\)。然后有两个 \(\min/\max\),考虑分类讨论:

  1. \(a_i'+2j-2i<a_{j+1}-1\)\(a_i'-2i+1<a_{j+1}-2j\)。这样里面那个 \(\min\) 的值就是 \(a'_i+2j-2i\)。然后还要使它 \(\leq a_j-1\),不然会值为 \(0\),即 \(a'_i-2i+1\geq a_j-2j\),然后值是 \(a'_i+2j-2i-a_j+1=\left(a'_i-2i+1\right)+(2j-a_j)\)。于是这个我们每次将 \(a'_i-2i+1\) 加入 BIT,然后数一下 \([a_j-2j,a_{j+1}-2j)\) 内的计数与和,就可以算了;
  2. \(a'_i+2j-2i\geq a_{j+1}-1\)\(a'_i-2i+1\geq a_{j+1}-2j\)。这样值就是 \(a_{j+1}-1-a_j+1=a_{j+1}-a_j\),这个只跟 \(j\) 有关,于是后缀计数一下乘一下即可。

但是这样统计答案的次数是不跟 \(n\) 有关了,但是加入 BIT 的次数还跟 \(n\) 有关。于是我们考虑一个 gap 整体加入,那这显然计数是区间加,而和的失职,其实是区间加等差数列。我们考虑线段树维护,那么这个区间加等差数列、区间求和其实是个经典问题,只需要维护懒标记,然后下传的时候就用一下等差数列求和公式就可以了,可以 \(\mathrm O(\log)\) 维护。这样总复杂度就是线对了。

然后每次不能重新建树,会 T,必须每次撤销。

code

posted @ 2020-12-04 09:36  ycx060617  阅读(126)  评论(0编辑  收藏  举报