forked from EndlessCheng/codeforces-go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsqrt_decomposition.go
117 lines (106 loc) · 3.74 KB
/
sqrt_decomposition.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package copypasta
import (
"math"
"sort"
)
/* 分块思想 Sqrt Decomposition
一种技巧:组合两种算法从而降低复杂度 O(n^2) -> O(n√n)
参考 Competitive Programmer’s Handbook Ch.27
题目花样很多,下面举个例子
有 n 个对象,每个对象有一个「关于其他对象的统计量」ci(一个数、一个集合的元素个数,等等)
为方便起见,假设 ∑ci 的数量级和 n 一样,下面用 n 表示 ∑ci
当 ci > √n 时,这样的对象不超过 √n 个,暴力枚举这些对象之间的关系(或者,该对象与其他所有对象的关系),时间复杂度为 O(n) 或 O(n√n)。此乃算法一
当 ci ≤ √n 时,这样的对象有 O(n) 个,由于统计量 ci 很小,暴力枚举当前对象的统计量,时间复杂度为 O(n√n)。此乃算法二
这样,以 √n 为界,我们将所有对象划分成了两组,并用两个不同的算法处理
这两种算法是看待同一个问题的两种不同方式,通过恰当地组合这两个算法,复杂度由 O(n^2) 降至 O(n√n)
注意:**枚举时要做到不重不漏**
可以从这题上手 https://codeforces.com/problemset/problem/797/E
https://codeforces.com/problemset/problem/425/D
https://codeforces.com/problemset/problem/677/D
https://codeforces.com/problemset/problem/1207/F
https://codeforces.com/problemset/problem/1468/M 或四元环
LCP16 https://leetcode-cn.com/problems/you-le-yuan-de-you-lan-ji-hua/
*/
// TIPS: n 的整数分拆中,不同数字的个数至多有 O(√n) 种
/* 分散层叠算法 Fractional Cascading
https://en.wikipedia.org/wiki/Fractional_cascading
https://www.luogu.com.cn/blog/DPair2005/fen-san-ceng-die-suan-fa-xue-xi-bi-ji
https://www.luogu.com.cn/problem/P6466
*/
/*
分块数据结构
https://oi-wiki.org/ds/decompose/
https://oi-wiki.org/ds/block-array/
【推荐】https://www.luogu.com.cn/blog/220037/Sqrt1
浅谈基础根号算法——分块 https://www.luogu.com.cn/blog/deco/qian-tan-ji-chu-gen-hao-suan-fa-fen-kuai
todo https://www.csie.ntu.edu.tw/~sprout/algo2018/ppt_pdf/root_methods.pdf
题目推荐 https://cp-algorithms.com/data_structures/sqrt_decomposition.html#toc-tgt-8
好题 https://codeforces.com/problemset/problem/91/E
todo 动态逆序对 https://www.luogu.com.cn/problem/P3157 https://www.luogu.com.cn/problem/UVA11990
https://cp-algorithms.com/sequences/rmq.html
todo https://www.luogu.com.cn/problem/P3396
https://codeforces.com/problemset/problem/1207/F
https://codeforces.com/contest/455/problem/D
*/
func sqrtDecompositionCollections() {
min := func(a, b int) int {
if a < b {
return a
}
return b
}
max := func(a, b int) int {
if a > b {
return a
}
return b
}
type block struct {
l, r int // [l,r]
origin, sorted []int
//lazyAdd int
}
var blocks []block
sqrtInit := func(a []int) {
n := len(a)
blockSize := int(math.Sqrt(float64(n)))
//blockSize := int(math.Sqrt(float64(n) * math.Log2(float64(n+1))))
blockNum := (n-1)/blockSize + 1
blocks = make([]block, blockNum)
for i, v := range a {
j := i / blockSize
if i%blockSize == 0 {
blocks[j] = block{l: i, origin: make([]int, 0, blockSize)}
}
blocks[j].origin = append(blocks[j].origin, v)
}
for i := range blocks {
b := &blocks[i]
b.r = b.l + len(b.origin) - 1
b.sorted = append([]int(nil), b.origin...)
sort.Ints(b.sorted)
}
}
sqrtOp := func(l, r int, v int) { // [l,r], starts at 0
for i := range blocks {
b := &blocks[i]
if b.r < l {
continue
}
if b.l > r {
break
}
if l <= b.l && b.r <= r {
// do op on full block
} else {
// do op on part block
bl := max(b.l, l)
br := min(b.r, r)
for j := bl - b.l; j <= br-b.l; j++ {
// do b.origin[j]...
}
}
}
}
_ = []interface{}{sqrtInit, sqrtOp}
}