来讲一个不常用(不是)但是有用的算法吧。

大纲

  1. 大概思路
  2. 例题

1.大概思路

一般这种题我们都会分为两类:
k<=sqrt(n)和k>sqrt(n)
然而我们一般是对于第一种情况预处理或者标记(反正不是直接处理),第二种情况暴力。
在这些根号分治的题目中可以使得单次复杂度不超过sqrt(n)

2.例题

luogu P3396

题目链接
给你一个长度为 n n n 的序列和 m m m 个操作,每次操作有两种类型:

  1. 询问下标模 x x x 后为 y y y 的所有数之和;
  2. 修改第 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)显然可以预处理。
否则,就直接暴力。

更多推荐