前言
简单记录一下div2 825的一个好题 ~ ~。
题意1
一个长度为
m
m
m 的序列
b
b
b是好序列,当且仅当对于所有的
i
,
(
1
≤
i
≤
m
)
i,(1 \le i \le m)
i,(1≤i≤m),
b
i
≤
i
b_i \le i
bi≤i。
现在求序列
a
a
a 的所有连续子序列中,好序列有多少个。
思路
记
f
i
f_i
fi为:以
a
i
a_i
ai 为结尾的好序列
[
a
j
.
.
a
i
−
1
a
i
]
[a_j..a_{i - 1}a_i]
[aj..ai−1ai]的个数。
根据定义
f
i
=
j
的取值方案数
=
l
e
n
(
[
a
j
.
.
a
i
−
1
a
i
]
)
≤
a
i
f_i =j的取值方案数= len([a_j..a_{i - 1}a_i]) \le a_i
fi=j的取值方案数=len([aj..ai−1ai])≤ai
再根据转移递推关系,
f
i
f_i
fi的所有合法方案可以从
f
i
−
1
f_{i -1}
fi−1 的合法方案后面接一个
a
i
a_i
ai 以及序列 [
a
i
a_i
ai] 得来,所以
f
i
≤
f
i
−
1
+
1
f_i \le f_{i-1}+1
fi≤fi−1+1。
f
i
=
m
i
n
(
f
i
−
1
+
1
,
a
i
)
。
f_i = min(f_{i - 1} + 1, a_i)。
fi=min(fi−1+1,ai)。
答案为
∑
i
=
1
n
f
i
\sum_{i=1}^{n}f_i
∑i=1nfi
题意2
接 题意1,给定
q
q
q 个 独立的 询问:p x
。
令
a
p
:
=
x
a_p := x
ap:=x。
求序列
a
a
a 的连续子序列中好序列的个数。
思路
仔细观察,可以发现,对于
a
p
a_p
ap 改变之后,
f
1..
(
p
−
1
)
f_{1..(p-1)}
f1..(p−1) 的值并不会改变。
所以,我们只要关注
f
p
.
.
n
f_{p..n}
fp..n 如何改变。
根据
f
f
f 序列的计算方法,我们可以得出修改后的
f
p
=
m
i
n
(
f
p
−
1
+
1
,
x
)
f_p = min(f_{p - 1}+1,x)
fp=min(fp−1+1,x)
此时
f
f
f中,
f
p
f_p
fp之后的一段序列 会变成形如
[
f
p
,
f
p
+
1
+
1
,
f
p
+
2
+
2
,
.
.
.
,
f
p
+
k
+
k
]
[f_p ,f_{p + 1} + 1,f_{p + 2}+2,...,f_{p +k}+k]
[fp,fp+1+1,fp+2+2,...,fp+k+k]。
我们需要知道
k
k
k 是多少。
由
f
i
f_i
fi 的计算公式,可以推测出:
k
k
k 就是满足条件
a
p
+
d
≤
f
p
+
d
a_{p + d} \le f_p + d
ap+d≤fp+d 中
d
d
d 的最小值减1 (二分可得)。
形式上可以这样理解:在
f
d
+
p
f_{d+p}
fd+p 之前,所有
f
j
(
p
≤
j
≤
p
+
d
)
f_j (p \le j\le p+d)
fj(p≤j≤p+d) 的最大值约束都来自
f
p
f_p
fp。
从
f
d
+
p
f_{d + p}
fd+p 开始,
f
j
(
d
+
p
≤
j
≤
n
)
f_j(d + p \le j \le n)
fj(d+p≤j≤n) 的最大值约束一开始来自
a
d
+
p
a_{d+p}
ad+p。
故,令
f
d
+
p
=
a
d
+
p
f_{d+p} = a_{d+p}
fd+p=ad+p, 然后重新按照转移方程计算所有的
f
j
(
j
≥
p
+
d
)
f_j(j \ge p + d)
fj(j≥p+d)。
我们可以先预处理所有的,令
f
i
=
a
i
f_{i} = a_{i}
fi=ai,
s
u
m
i
=
∑
j
=
i
n
f
j
sum_i = \sum_{j=i}^{n}f_j
sumi=∑j=infj。
可以倒着预处理,当我们令
f
i
=
a
i
f_i = a_i
fi=ai时,
f
i
f_i
fi 之后的一段序列会变成形如
[
f
i
,
f
i
+
1
+
1
,
f
i
+
2
+
2
,
.
.
.
,
f
i
+
k
+
k
]
[f_i ,f_{i + 1} + 1,f_{i+2}+2,...,f_{i +k}+k]
[fi,fi+1+1,fi+2+2,...,fi+k+k]。
这一点与上面提到的修改操作一样,若
p
=
k
+
1
p = k + 1
p=k+1, 此时
s
u
m
p
sum_p
sump已经求得。
所以
s
u
m
i
=
Σ
[
f
i
,
f
i
+
1
+
1
,
f
i
+
2
+
2
,
.
.
.
,
f
i
+
k
+
k
]
+
s
u
m
p
sum_i = \Sigma [f_i ,f_{i + 1} + 1,f_{i+2}+2,...,f_{i +k}+k] +sum_p
sumi=Σ[fi,fi+1+1,fi+2+2,...,fi+k+k]+sump
其中
Σ
[
f
i
,
f
i
+
1
+
1
,
f
i
+
2
+
2
,
.
.
.
,
f
i
+
k
+
k
]
\Sigma [f_i ,f_{i + 1} + 1,f_{i+2}+2,...,f_{i +k}+k]
Σ[fi,fi+1+1,fi+2+2,...,fi+k+k] 是一个等差数列和。
完成预处理之后,根据上文的分析,可以得出,询问的答案会变成:
∑
i
=
1
p
f
i
+
∑
[
f
i
+
1
+
1
,
f
i
+
2
+
2
,
.
.
.
,
f
i
+
k
+
k
]
+
s
u
m
k
+
1
\sum_{i = 1}^{p}f_i+\sum [f_{i + 1} + 1,f_{i+2}+2,...,f_{i +k}+k]+sum_{k +1}
∑i=1pfi+∑[fi+1+1,fi+2+2,...,fi+k+k]+sumk+1
本题中对序列f的二分,可以使用线段树上二分或者st表 + 二分答案实现,具体实现方法已经广为人知,就不做补充了。