Codeforces Round #825 (Div. 2) C. Good Subarrays

前言

简单记录一下div2 825的一个好题 ~ ~。

题意1

一个长度为 m m m 的序列 b b b是好序列,当且仅当对于所有的 i , ( 1 ≤ i ≤ m ) i,(1 \le i \le m) i,(1im), b i ≤ i b_i \le i bii
现在求序列 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..ai1ai]的个数。
根据定义 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..ai1ai])ai
再根据转移递推关系, f i f_i fi的所有合法方案可以从 f i − 1 f_{i -1} fi1 的合法方案后面接一个 a i a_i ai 以及序列 [ a i a_i ai] 得来,所以 f i ≤ f i − 1 + 1 f_i \le f_{i-1}+1 fifi1+1
f i = m i n ( f i − 1 + 1 , a i ) 。 f_i = min(f_{i - 1} + 1, a_i)。 fi=min(fi1+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..(p1) 的值并不会改变。
所以,我们只要关注 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(fp1+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+dfp+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(pjp+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+pjn) 的最大值约束一开始来自 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(jp+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表 + 二分答案实现,具体实现方法已经广为人知,就不做补充了。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值