来讲一个不常用(不是)但是有用的算法吧。
大纲
- 大概思路
- 例题
1.大概思路
一般这种题我们都会分为两类:
k<=sqrt(n)和k>sqrt(n)
然而我们一般是对于第一种情况预处理或者标记(反正不是直接处理),第二种情况暴力。
在这些根号分治的题目中可以使得单次复杂度不超过sqrt(n)
2.例题
luogu P3396
题目链接
给你一个长度为
n
n
n 的序列和
m
m
m 个操作,每次操作有两种类型:
- 询问下标模 x x x 后为 y y y 的所有数之和;
- 修改第 x x x 个数;
对于 10 % 10\% 10%的数据,有 n ≤ 1000 n\leq 1000 n≤1000, m ≤ 1000 m\leq 1000 m≤1000。
对于 60 % 60\% 60% 的数据,有 n ≤ 100000 n\leq 100000 n≤100000, m ≤ 100000 m\leq 100000 m≤100000。
对于 100 % 100\% 100% 的数据,有 n ≤ 150000 n\leq 150000 n≤150000, m ≤ 150000 m\leq 150000 m≤150000。
保证所有数据合法,且 1 ≤ v a l u e i ≤ 1000 1\leq \mathrm{value}_i \leq 1000 1≤valuei≤1000。
看下数据范围支持带
s
q
r
t
sqrt
sqrt,考虑根号分治。
若
y
>
s
q
r
t
(
n
)
y>sqrt(n)
y>sqrt(n) 时,显然此时暴力的时间复杂度
<
=
s
q
r
t
(
n
)
<=sqrt(n)
<=sqrt(n),所以可以直接暴力。
当
y
<
=
s
q
r
t
(
n
)
y<=sqrt(n)
y<=sqrt(n) 时,暴力时间复杂度很高,此时发现可以预处理所有
y
<
=
s
q
r
t
(
n
)
y<=sqrt(n)
y<=sqrt(n) 的所有查询情况,这样的预处理复杂度为
O
(
n
s
q
r
t
(
n
)
)
O(nsqrt(n))
O(nsqrt(n)),可以接受。
CF797E
Array Queries
题面翻译
- 给定长度为 n n n 的序列 a a a。 m m m 次询问。
- 每次询问给出 p , k p,k p,k。您要不断地执行操作 p ← p + a p + k p\gets p+a_p+k p←p+ap+k,直到 p > n p>n p>n 为止。询问的答案为操作次数。
- 1 ≤ n , q ≤ 1 0 5 1\le n,q\le 10^5 1≤n,q≤105, 1 ≤ a i ≤ n 1\le a_i\le n 1≤ai≤n, 1 ≤ p , k ≤ n 1\le p,k\le n 1≤p,k≤n。
这里发现若k<=sqrt(n)显然可以预处理。
否则,就直接暴力。