根号分治例题
哈希冲突
题意: 求
∑
i
=
0
i
∗
x
+
y
<
=
n
a
[
i
∗
x
+
y
]
\sum_{i = 0}^{ix+y<=n} a[ix+y]
∑i=0i∗x+y<=na[i∗x+y]为多少,单点修改
根号分治, 首先发现数据范围都为
1
e
5
1e5
1e5级别的,考虑如何入手这道题
对于查询
1.发现如果
x
>
n
x > \sqrt{n}
x>n,那么暴力调的时间复杂度最多为
n
n
n\sqrt{n}
nn,
2.如果
x
<
n
x < \sqrt{n}
x<n,我们发现可以进行预处理,
f
[
i
]
[
j
]
f[i][j]
f[i][j]表示
m
o
d
i
mod i
modi,为
j
j
j的
s
u
m
sum
sum,
n
n
n\sqrt{n}
nn预处理,
对于修改
情况一 : 暴力修改
情况二 : 暴力修改
最差时间复杂度
O
(
n
n
l
o
g
n
)
O(n\sqrt{n}log_n)
O(nnlogn)
Time to Raid Cowavans
和上一题一模一样,只是规定了一个起点,前缀作差+差分即可
Array Queries
相同的处理方法
[ARC150B] Make Divisible
整除分块
由于要计算
k
(
B
+
Y
)
=
=
A
+
X
k(B + Y) == A + X
k(B+Y)==A+X,
(
X
+
Y
)
m
i
n
(X +Y)_{min}
(X+Y)min
可以得到
k
=
⌈
A
B
+
Y
⌉
k=\left \lceil \frac{A}{B+Y} \right \rceil
k=⌈B+YA⌉
由整除分块可得,最多有
n
\sqrt{n}
n个不同的
k
k
k
由于
y
=
k
∗
(
B
+
Y
)
−
A
y = k*(B+Y)-A
y=k∗(B+Y)−A,
Y
=
B
+
Y
−
B
Y = B+Y-B
Y=B+Y−B
所以,在
k
k
k相同的时候,块内的左端点所对应的是最小值
不妨设
l
=
B
+
Y
l=B+Y
l=B+Y
则
k
=
⌈
A
l
⌉
k=\left \lceil \frac{A}{l} \right \rceil
k=⌈lA⌉
则
k
=
⌊
A
+
l
−
1
l
⌋
k = \left \lfloor \frac{A+l-1}{l} \right \rfloor
k=⌊lA+l−1⌋
对于每一种
k
k
k,
r
r
r的取值是什么
r
=
m
a
x
(
i
)
i
∗
k
<
=
A
+
l
−
1
r= max(i){i*k<=A+l-1}
r=max(i)i∗k<=A+l−1
则
r
=
A
+
l
−
1
k
r=\frac{A+l-1}{k}
r=kA+l−1
求解即可,复杂度
2
n
n
2n\sqrt{n}
2nn
[ABC258G] Triangle
三元环计数的弱弱弱化版,考虑按边求解,bitset优化即可
无向图三元环计数
解法1:
考虑将一个无向图重新建成一个有向图且三元环的个数不变,考虑将度数小的边指向度数大的边,如果度数相同,则按编号小的指向编号大的边,这样肯定是一个
D
A
G
DAG
DAG,计数则枚举每一个点,看每一条出边的点的出边是否与当前枚举的点相同,复杂度经过证明为
n
n
n\sqrt{n}
nn
解法2:考虑优化弱化版,按边枚举,用边中度数小的点,枚举它的出边,看出边的v是否与枚举的边相连,用hash判断
时间复杂度
3
n
s
q
r
t
n
3nsqrt{n}
3nsqrtn
P7828 [CCO2021] Swap Swap Sort
分析题意,其实为基于排列
S
S
S,求
A
A
A的逆序对个数(对于给定排列规则且临项交换可看做逆序对个数)
O
(
n
q
l
o
g
n
)
O(nqlog_{n})
O(nqlogn) 做法,对于每次的询问重新做一遍逆序对
优化, 对于排列
S
S
S而言,每次交换都是临项交换,考虑计算对于上次答案的增量,
如果原先排列为
(
x
,
y
)
(x, y)
(x,y),更改为
(
y
,
x
)
(y,x)
(y,x),则增加
g
e
t
(
y
,
x
)
get(y, x)
get(y,x)(即在所有
y
y
y的前面有多少个
x
x
x), 减少
g
e
t
(
x
,
y
)
get(x, y)
get(x,y),总复度无法过掉此题
考虑
g
e
t
(
x
,
y
)
get(x,y)
get(x,y)与
g
e
t
(
y
,
x
)
get(y,x)
get(y,x)的和其实为
s
i
z
[
x
]
∗
s
i
z
[
y
]
siz[x]*siz[y]
siz[x]∗siz[y],这样作差来计算,
具体的,如果只计算
g
e
t
(
x
,
y
)
get(x,y)
get(x,y)来统计答案,则增量为
s
i
z
[
x
]
∗
s
i
z
[
y
]
−
2
∗
g
e
t
(
x
,
y
)
siz[x]siz[y]-2get(x,y)
siz[x]∗siz[y]−2∗get(x,y)
这样用较小的来计算答案,如果对于计算
g
e
t
(
x
,
y
)
get(x,y)
get(x,y)如果出现过直接加上增量,时间复杂度分析
1.如果
s
i
z
[
x
]
,
s
i
z
[
y
]
siz[x],siz[y]
siz[x],siz[y]中的较小数小于
n
\sqrt{n}
n,则复杂度显然小于
O
(
n
∗
n
l
o
g
n
)
O(n * \sqrt{n}log_{n})
O(n∗nlogn)
2.如果
s
i
z
[
x
]
,
s
i
z
[
y
]
siz[x],siz[y]
siz[x],siz[y]中的较小数大于
n
\sqrt{n}
n,则最多有
n
n
\frac{n}{\sqrt{n}}
nn中不同的数,考虑最多
Q
Q
Q次询问,显然对于每种数而言
s
i
z
=
n
siz=\sqrt{n}
siz=n可以使程序时间复杂度最劣,最差时间复杂度为
O
(
n
n
l
o
g
n
)
O(n\sqrt{n}log_{n})
O(nnlogn)
[ABC259Ex] Yet Another Path Counting
套路题,发现颜色之间互不影响,考虑按颜色分类,如果某种颜色出现次数小于阈值
B
B
B,则两两匹配,直接组合数计算答案,
如果大于阈值
B
B
B,则考虑DP计算答案,
f
[
i
]
[
j
]
f[i][j]
f[i][j]表示以
i
,
j
i,j
i,j为路径结尾的答案。
则时间复杂度为
O
(
n
∗
n
B
B
∗
B
+
n
∗
n
B
∗
n
∗
n
)
O(\frac{nn}{B}BB+\frac{nn}{B}n*n)
O(Bn∗nB∗B+Bn∗n∗n∗n)
发现阈值为
n
n
n最优秀,时间复杂度为
O
(
n
3
)
O(n^3)
O(n3)
根号分治可以是具体的分析时间复杂度,然后对于每种情况都给予一种解决方法,也可以只分析时间复杂度正确,然后统一处理
入手点一般为给出两种时间复杂度不是很优秀的方法然后组合在一起,或者类似启发式合并的方法用较小的哪一部分计算答案,可以证明时间复杂度为正确的
情况数与个数成反比时要注意根号分治
P3645 [APIO2015] 雅加达的摩天楼
直接分析复杂度,最多有
n
n
n个城市,
m
m
m条
d
o
g
e
doge
doge,考虑直接BFS,这样如果输入到了第1号
d
o
g
e
doge
doge所在的城市直接输出步数即可,
发现一条
d
o
g
e
doge
doge只会在第一次遍历到的时候让它跑才会最优,考虑设计状态
f
[
i
]
[
j
]
f[i][j]
f[i][j]表示第
i
i
i个城市是否被 第
j
j
j个
d
o
g
e
doge
doge遍历过
考虑分析复杂度
\qquad
如果
l
e
n
≤
n
len\le \sqrt{n}
len≤n 则最多有
n
n
n\sqrt{n}
nn个状态
\qquad
如果
l
e
n
≥
n
len \ge \sqrt{n}
len≥n 则最多跑
n
n
n\sqrt{n}
nn次
则直接跑BFS即可,
f
[
]
[
]
f[][]
f[][] 用
b
i
t
s
e
t
bitset
bitset存
Xenia and Tree
套路题;将操作序列分块
如果对于一个染色操作BFS染色复杂度为
O
(
n
)
O(n)
O(n),但多元BFS复杂度也为
O
(
n
)
O(n)
O(n)
考虑维护长度为
B
B
B的块只存染色操作
\qquad
如果块为满,则跑一次多元BFS
\qquad
如果块未满,则加入块中不跑
对于查询而言,则是当前的
d
i
s
[
]
dis[]
dis[](表示到染色点的最近距离),与在块中中的染色点的树上路径长度的较小值
复杂度为
O
(
m
B
∗
n
+
m
∗
B
)
O(\frac{m}{B}n+mB)
O(Bm∗n+m∗B) 可得
B
B
B取
n
\sqrt{n}
n优秀
[ABC259Ex] Yet Another Path Counting
套路题: 考虑颜色与颜色之间没有关系,按颜色分组
\qquad
若一个颜色个数非常少,可以枚举每两个点计算方案
\qquad
若一个颜色个数非常多,直接跑
D
P
DP
DP
设置阈值
B
B
B
则复杂度为
O
(
n
2
B
∗
B
∗
B
+
n
2
B
∗
n
∗
n
)
O(\frac{n2}{B}*B*B+\frac{n2}{B}nn)
O(Bn2∗B∗B+Bn2∗n∗n),易得
B
B
B取
n
n
n时优秀
Tree Queries
好题
考虑对于一次操作一对于各点的期望影响
对于
v
v
v,若
u
u
u为
v
v
v,则增量为
n
∗
d
n*d
n∗d
若
u
u
u不为
v
v
v
若
v
v
v为树根,则对于每一个点
u
u
u,若它所在的子树为
s
o
n
[
u
]
son[u]
son[u],则增量为
n
−
s
o
n
[
u
]
n
∗
d
\frac{n-son[u]}{n}*d
nn−son[u]∗d
若
v
v
v不为树根,则对于
v
v
v子树中的点于情况一同理,若不在
v
v
v的子树中,则增量为
s
i
z
[
v
]
n
∗
d
\frac{siz[v]}{n}*d
nsiz[v]∗d
解法一: 考虑树剖对子树操作,发现如果为菊花图且每次都给花心操作复杂度太高
考虑差分,发现只给重儿子进行操作,然后在每一个重儿子上存修改的累加和
如何查询,对于每一个点,首先查它在树状数组中的值,然后往上跳链,加入往上跳的链的链头的的影响
复杂度
O
(
n
l
o
g
n
2
)
O(nlog_{n}^2)
O(nlogn2)
解法二:对于儿子多的考虑儿子大小一样的看成一个点,直接枚举儿子操作即可

浙公网安备 33010602011771号