等差子序列
$Description$
$Soltuion$
权值线段树好题。
先知道一个东西: $a_i <= n\ \&\&\ a_i != a_j$
首先有一种很显然的 $O(n^2)$ 算法,枚举第一个与第二个,用一个桶记录,直接询问第三个元素是否存在即可。
然后考虑如何优化这个玩意,首先想到枚举第一项,然后优化找第二项与第三项的过程。
好像不太行,考虑把等差数列的式子移个项再做。
有
$$
a_j - a_i = a_k - a_j
$$
移项得
$$
2 \times a_j = a_i + a_k
$$
然后考虑枚举 $a_j$ ,询问 $a_j - x$ 与 $a_j + x$ 是否在同侧,在异侧就说明找得到这样的等差数列。
考虑用 $Hash + SegmentTree$ 实现这个过程。
我们考虑对于一个序列内有一个数,设他左边有一个 $a_i + x\ (1 <= a_i + x <= n)$ ,那么对于一个数 $a_i - x\ (1 <= a_i - x <= n)$ ,他必然在这个数的左侧或右侧,如果在右侧,那么就找到了一个等差数列,所以我们考虑在左侧寻找这么一个数。
我们用一个状态 $S$ 记录一个数是否在这段区间内出现过,出现过为 $1$ ,没出现为 $0$ 。
然后我们把这一串状态 $Hash$ 起来,从 $1 \to i - 1$ 正着做一遍, $n \to i + 1$ 反着做一遍。如果两段这个元素的哈希值不相同,说明到目前为止这个数一侧的某一个数出现过,另一侧的这个数对应的数没出现,就说明我们找到了一个等差数列。
$Code:$
1 |
|