Skip to content

Commit

Permalink
upd
Browse files Browse the repository at this point in the history
  • Loading branch information
EndlessCheng committed May 2, 2023
1 parent 106a76f commit bcfae0a
Show file tree
Hide file tree
Showing 14 changed files with 111 additions and 47 deletions.
18 changes: 17 additions & 1 deletion copypasta/bits.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ https://codeforces.com/problemset/problem/1325/D
https://codeforces.com/problemset/problem/1368/D
https://atcoder.jp/contests/abc050/tasks/arc066_b
+ 与 ^ https://codeforces.com/problemset/problem/1732/C2
max(a,b) = (a + b + abs(a-b)) / 2
结合律:(a&b)^(a&c) = a&(b^c) 其他符号类似
Expand Down Expand Up @@ -84,6 +86,12 @@ https://oeis.org/A178910 异或和 因子
异或与 mex
[1800·hot10] https://codeforces.com/problemset/problem/1554/C
异或与 <
a < b,无法通过两边异或同一个数来做式子变形
此时可以枚举高 k 个比特位是相等的,而第 k+1 个比特位 a 中是 0,b 中是 1
人为地创造出「相等」这个条件
https://codeforces.com/problemset/problem/1720/D2
https://oeis.org/A038712 a(n) = n^(n-1) = 1, 3, 1, 7, 1, 3, 1, 15, 1, ...
https://oeis.org/A080277 A038712 的前缀和 => a(n) = n + 2*a(n/2)
Expand Down Expand Up @@ -176,6 +184,12 @@ https://oeis.org/A090994 Number of meaningful differential operations of the n-t
a(k+5) = a(k+4) + 4*a(k+3) - 3*a(k+2) - 3*a(k+1) + a(k)
相关题目 LC1215 https://leetcode-cn.com/problems/stepping-numbers/
二进制字符串
https://oeis.org/A052944 a(n) = 2^n + n - 1 Shortest length of bit-string containing all bit-strings of given length n
https://math.stackexchange.com/questions/4509158/length-of-the-shortest-binary-string-that-contains-as-substrings-all-unique-n-le
https://en.wikipedia.org/wiki/De_Bruijn_sequence
应用 https://codeforces.com/problemset/problem/1469/E
套路题 https://codeforces.com/problemset/problem/1415/D
按位归纳 https://codeforces.com/problemset/problem/925/C
*/
Expand Down Expand Up @@ -479,7 +493,7 @@ func _(x int) {
// 是否有两个相邻的 1 有 https://oeis.org/A004780 没有 https://oeis.org/A003714
hasAdjacentOnes := func(v uint) bool { return v>>1&v > 0 }

// 是否有两个相邻的 0(不考虑前导零) 有 https://oeis.org/A004753 没有 http://oeis.org/A003754
// 是否有两个相邻的 0(不考虑前导零) 有 https://oeis.org/A004753 没有 https://oeis.org/A003754
hasAdjacentZeros := func(v uint) bool {
v |= v >> 1 // 若没有相邻的 0,则 v 会变成全 1 的数
return v&(v+1) > 0
Expand Down Expand Up @@ -538,7 +552,9 @@ func _(x int) {
// &: LC1521 https://leetcode-cn.com/problems/find-a-value-of-a-mysterious-function-closest-to-target/
// GCD: 原理:固定右端点时,向左扩展,GCD 要么不变,要么至少减半,所以固定右端点时,只有 O(log U) 个 GCD
// LC2447 https://leetcode.cn/problems/number-of-subarrays-with-gcd-equal-to-k/
// LC2654 https://leetcode.cn/problems/minimum-number-of-operations-to-make-all-array-elements-equal-to-1/ https://www.dotcpp.com/oj/problem2709.html
// https://codeforces.com/edu/course/2/lesson/9/2/practice/contest/307093/problem/G
// https://codeforces.com/problemset/problem/891/A
// https://codeforces.com/problemset/problem/475/D (见下面的 bitOpTrickCnt)
// https://codeforces.com/problemset/problem/1632/D (见下面的 bitOpTrickCnt)
// 已知所有 GCD 还原数组 a https://codeforces.com/problemset/problem/894/C
Expand Down
6 changes: 6 additions & 0 deletions copypasta/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import (
)

// Competitive Programming Roadmap (target: [gray, blue]) https://codeforces.com/blog/entry/111099
// A way to Practice Competitive Programming : From Rating 1000 to 2400+ https://codeforces.com/blog/entry/66909
// https://cin.ufpe.br/~fbma/Crack/%5BTutorial%5D%20A%20Way%20to%20Practice%20Competitive%20Programming.pdf

// 解决问题的一般方法 https://codeforces.com/blog/entry/92248?#comment-809401
// General ideas https://codeforces.com/blog/entry/48417
Expand Down Expand Up @@ -64,6 +66,9 @@ https://codeforces.com/problemset/problem/1369/C
如果 y 交换后也不是最小值,那么答案变大了 x-y。
无论如何,这样交换都不会使答案变小,因此前 k 大的数一定可以作为最大值。
提示 2:然后来说最小值。a 的最小值必然要分到某个组中,为了「跳过」尽量多的较小的数,优先把 a 中较小的数分到 w 较大的组中。所以 a 从小到大遍历,w 从大到小遍历。
https://codeforces.com/problemset/problem/1479/B1 https://codeforces.com/problemset/problem/1479/B2
https://www.luogu.com.cn/blog/wsyhb/post-ti-xie-cf1479b1-painting-the-array-i
1505. 最多 K 次交换相邻数位后得到的最小整数 https://leetcode.cn/problems/minimum-possible-integer-after-at-most-k-adjacent-swaps-on-digits/
每次取数组中大于 0 的连续一段同时减 1,求使数组全为 0 的最少操作次数
https://leetcode.cn/problems/minimum-number-of-increments-on-subarrays-to-form-a-target-array/solutions/371326/xing-cheng-mu-biao-shu-zu-de-zi-shu-zu-zui-shao-ze/
Expand All @@ -85,6 +90,7 @@ https://codeforces.com/problemset/problem/558/C
https://codeforces.com/problemset/problem/1610/E
https://codeforces.com/problemset/problem/1811/C
https://codeforces.com/problemset/problem/1822/D
https://codeforces.com/problemset/problem/1608/C 对拍找反例
构造
LC767 https://leetcode.cn/problems/reorganize-string/
Expand Down
3 changes: 3 additions & 0 deletions copypasta/fenwick_tree.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import "sort"

/* 树状数组(Fenwick Tree),二叉索引树(Binary Index Tree, BIT)
https://en.wikipedia.org/wiki/Fenwick_tree
原论文 https://doi.org/10.1002/spe.4380240306
树状数组 tree 的基本用途是维护序列 a 的前缀和(tree 和 a 的下标都从 1 开始)
tree[i] = a[i-lowbit(i)+1] + ... + a[i]
看图 https://oi-wiki.org/ds/fenwick/
Expand Down Expand Up @@ -37,6 +38,8 @@ https://algs4.cs.princeton.edu/code/edu/princeton/cs/algs4/FenwickTree.java.html
多变量统计 https://codeforces.com/problemset/problem/1194/E
T4 https://www.nowcoder.com/discuss/1022136
三元逆序对 https://codeforces.com/problemset/problem/61/E
最多交换 k 次相邻字母后,得到的最小字典序
- LC1505 https://leetcode.cn/problems/minimum-possible-integer-after-at-most-k-adjacent-swaps-on-digits/
整除对统计 https://codeforces.com/problemset/problem/301/D
区间统计技巧 https://codeforces.com/problemset/problem/369/E
区间包含计数 https://codeforces.com/problemset/problem/652/D
Expand Down
14 changes: 12 additions & 2 deletions copypasta/games.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ todo 阶梯博弈 https://codeforces.com/blog/entry/44651
入门分类讨论 https://codeforces.com/problemset/problem/78/C
三定理的模板题 https://codeforces.com/problemset/problem/1033/C
https://atcoder.jp/contests/dp/tasks/dp_k
1-2-K Game https://codeforces.com/problemset/problem/1194/D 我的题解 https://www.acwing.com/file_system/file/content/whole/index/content/3179098/
TODO: 题目推荐 https://blog.csdn.net/ACM_cxlove/article/details/7854526
一道不错的有向图博弈 https://codeforces.com/problemset/problem/936/B
todo 威佐夫博弈 https://www.luogu.com.cn/problem/P2252
Expand All @@ -33,7 +34,7 @@ todo https://codeforces.com/problemset/problem/138/D (注:这是挑战上推
通过必败态去筛必胜态 https://ac.nowcoder.com/acm/contest/11166/A
两端取数问题 https://atcoder.jp/contests/dp/tasks/dp_l LC486 https://leetcode-cn.com/problems/predict-the-winner/ LC877 https://leetcode-cn.com/problems/stone-game/
*/
func gameTheoryCollection() {
func _() {
{
// 基础打表
p, q := 3, 4
Expand Down Expand Up @@ -128,8 +129,17 @@ func gameTheoryCollection() {
// todo 推荐论文《组合游戏略述——浅谈 SG 游戏的若干拓展及变形》
// todo Anti-SG
//
// 参考《福州大学 ACMICPC 集训队资料》9.4
// 常见限制条件下的 SG 值:
// 最多取 m 个:SG(n) = n%(m+1)
// 只能取奇数个:SG(n) = n%2
// 只能取 2^i 个:SG(n) = n%3
// 只能取 p^i 个(p 为奇素数):SG(n) = n%2
//
// 整数分拆博弈 https://codeforces.com/problemset/problem/87/C
// 类似取石子 https://codeforces.com/problemset/problem/850/C
// 取石子变形
// - https://codeforces.com/problemset/problem/850/C
// - https://codeforces.com/problemset/problem/1823/E
// todo https://www.luogu.com.cn/problem/P2148

// 剪纸博弈
Expand Down
52 changes: 26 additions & 26 deletions copypasta/heap.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,11 @@ https://codeforces.com/problemset/problem/1701/D

type hp struct{ sort.IntSlice }

//func (h hp) Less(i, j int) bool { return h.IntSlice[i] > h.IntSlice[j] } // 加上这行变成最大堆
func (h *hp) Push(v interface{}) { h.IntSlice = append(h.IntSlice, v.(int)) }
func (h *hp) Pop() interface{} { a := h.IntSlice; v := a[len(a)-1]; h.IntSlice = a[:len(a)-1]; return v }
func (h *hp) push(v int) { heap.Push(h, v) }
func (h *hp) pop() int { return heap.Pop(h).(int) } // 稍微封装一下,方便使用
//func (h hp) Less(i, j int) bool { return h.IntSlice[i] > h.IntSlice[j] } // 加上这行变成最大堆
func (h *hp) Push(v any) { h.IntSlice = append(h.IntSlice, v.(int)) }
func (h *hp) Pop() any { a := h.IntSlice; v := a[len(a)-1]; h.IntSlice = a[:len(a)-1]; return v }
func (h *hp) push(v int) { heap.Push(h, v) }
func (h *hp) pop() int { return heap.Pop(h).(int) } // 稍微封装一下,方便使用

// EXTRA: 参考 Python,引入下面两个效率更高的方法(相比调用 push + pop)
// replace 弹出并返回堆顶,同时将 v 入堆
Expand All @@ -83,13 +83,13 @@ func (h *hp) pushPop(v int) int {
// 自定义类型(int64 可以替换成其余类型)
type hp64 []int64

func (h hp64) Len() int { return len(h) }
func (h hp64) Less(i, j int) bool { return h[i] < h[j] } // > 为最大堆
func (h hp64) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *hp64) Push(v interface{}) { *h = append(*h, v.(int64)) }
func (h *hp64) Pop() interface{} { a := *h; v := a[len(a)-1]; *h = a[:len(a)-1]; return v }
func (h *hp64) push(v int64) { heap.Push(h, v) }
func (h *hp64) pop() int64 { return heap.Pop(h).(int64) } // 稍微封装一下,方便使用
func (h hp64) Len() int { return len(h) }
func (h hp64) Less(i, j int) bool { return h[i] < h[j] } // > 为最大堆
func (h hp64) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *hp64) Push(v any) { *h = append(*h, v.(int64)) }
func (h *hp64) Pop() any { a := *h; v := a[len(a)-1]; *h = a[:len(a)-1]; return v }
func (h *hp64) push(v int64) { heap.Push(h, v) }
func (h *hp64) pop() int64 { return heap.Pop(h).(int64) } // 稍微封装一下,方便使用

//

Expand All @@ -108,8 +108,8 @@ type mh []*viPair // mh 指 modifiable heap
func (h mh) Len() int { return len(h) }
func (h mh) Less(i, j int) bool { return h[i].v < h[j].v } // > 为最大堆
func (h mh) Swap(i, j int) { h[i], h[j] = h[j], h[i]; h[i].hi = i; h[j].hi = j }
func (h *mh) Push(v interface{}) { *h = append(*h, v.(*viPair)) }
func (h *mh) Pop() interface{} { a := *h; v := a[len(a)-1]; *h = a[:len(a)-1]; return v }
func (h *mh) Push(v any) { *h = append(*h, v.(*viPair)) }
func (h *mh) Pop() any { a := *h; v := a[len(a)-1]; *h = a[:len(a)-1]; return v }
func (h *mh) push(v int64) *viPair { p := &viPair{v, len(*h)}; heap.Push(h, p); return p }
func (h *mh) pop() *viPair { return heap.Pop(h).(*viPair) }
func (h *mh) fix(i int) { heap.Fix(h, i) }
Expand Down Expand Up @@ -175,12 +175,12 @@ type minHp struct {
s int // 维护堆中元素之和
}

func (h minHp) Len() int { return len(h.a) }
func (h minHp) Less(i, j int) bool { return h.a[i].t < h.a[j].t }
func (h minHp) Swap(i, j int) { h.a[i], h.a[j] = h.a[j], h.a[i] }
func (h *minHp) Push(v interface{}) { h.s += v.(pair).t; h.a = append(h.a, v.(pair)) }
func (h *minHp) Pop() interface{} { v := h.a[len(h.a)-1]; h.s -= v.t; h.a = h.a[:len(h.a)-1]; return v }
func (h *minHp) push(v pair) { heap.Push(h, v) }
func (h minHp) Len() int { return len(h.a) }
func (h minHp) Less(i, j int) bool { return h.a[i].t < h.a[j].t }
func (h minHp) Swap(i, j int) { h.a[i], h.a[j] = h.a[j], h.a[i] }
func (h *minHp) Push(v any) { h.s += v.(pair).t; h.a = append(h.a, v.(pair)) }
func (h *minHp) Pop() any { v := h.a[len(h.a)-1]; h.s -= v.t; h.a = h.a[:len(h.a)-1]; return v }
func (h *minHp) push(v pair) { heap.Push(h, v) }
func (h *minHp) pushPop(v pair) pair {
if h.Len() > 0 && v.t > h.a[0].t {
h.s += v.t - h.a[0].t
Expand All @@ -195,12 +195,12 @@ type maxHp struct {
s int
}

func (h maxHp) Len() int { return len(h.a) }
func (h maxHp) Less(i, j int) bool { return h.a[i].t > h.a[j].t }
func (h maxHp) Swap(i, j int) { h.a[i], h.a[j] = h.a[j], h.a[i] }
func (h *maxHp) Push(v interface{}) { h.s += v.(pair).t; h.a = append(h.a, v.(pair)) }
func (h *maxHp) Pop() interface{} { v := h.a[len(h.a)-1]; h.s -= v.t; h.a = h.a[:len(h.a)-1]; return v }
func (h *maxHp) push(v pair) { heap.Push(h, v) }
func (h maxHp) Len() int { return len(h.a) }
func (h maxHp) Less(i, j int) bool { return h.a[i].t > h.a[j].t }
func (h maxHp) Swap(i, j int) { h.a[i], h.a[j] = h.a[j], h.a[i] }
func (h *maxHp) Push(v any) { h.s += v.(pair).t; h.a = append(h.a, v.(pair)) }
func (h *maxHp) Pop() any { v := h.a[len(h.a)-1]; h.s -= v.t; h.a = h.a[:len(h.a)-1]; return v }
func (h *maxHp) push(v pair) { heap.Push(h, v) }
func (h *maxHp) pushPop(v pair) pair {
if h.Len() > 0 && v.t < h.a[0].t {
h.s += v.t - h.a[0].t
Expand Down
3 changes: 3 additions & 0 deletions copypasta/math.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,8 @@ func _(abs func(int64) int64, max func(int64, int64) int64) {
todo https://atcoder.jp/contests/abc162/tasks/abc162_e
https://atcoder.jp/contests/abc206/tasks/abc206_e
todo 基于值域预处理的快速 GCD https://www.luogu.com.cn/problem/P5435
GCD = 1 的子序列个数 https://codeforces.com/problemset/problem/803/F https://ac.nowcoder.com/acm/problem/112055
见后面的 mu
Expand Down Expand Up @@ -2946,6 +2948,7 @@ https://en.wikipedia.org/wiki/Enumerative_combinatorics
https://en.wikipedia.org/wiki/Binomial_theorem
一些组合问题
https://codeforces.com/problemset/problem/1391/C 1500
https://codeforces.com/problemset/problem/213/B
https://codeforces.com/problemset/problem/300/C
https://codeforces.com/problemset/problem/520/E
Expand Down
2 changes: 2 additions & 0 deletions copypasta/math_fft.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ https://cp-algorithms.com/algebra/fft.html
https://algs4.cs.princeton.edu/code/edu/princeton/cs/algs4/FFT.java.html
https://algs4.cs.princeton.edu/code/edu/princeton/cs/algs4/Polynomial.java.html
用 FFT 做字符串匹配 https://zhuanlan.zhihu.com/p/267765026
Arrow product: How to enumerate directed graphs https://codeforces.com/blog/entry/115617
todo https://github.com/OI-wiki/gitment/discussions/670#discussioncomment-4496021
若多项式系数没有复数的话,可以构造多项式 H(x)=F(x)+G(x)i,把 F(x) 放实部,把 G(x) 放虚部,然后对 H(x) 跑一遍 DFT,之后把 H(x) 平方一下,可以得到
Expand All @@ -31,6 +32,7 @@ todo https://github.com/OI-wiki/gitment/discussions/670#discussioncomment-449602
模板题 https://www.luogu.com.cn/problem/P3803
todo 推式子 https://www.luogu.com.cn/problem/P3338 花絮 https://zhuanlan.zhihu.com/p/349249817
todo https://codeforces.com/problemset/problem/993/E
*/

type fft struct {
Expand Down
5 changes: 4 additions & 1 deletion copypasta/math_fwt.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@ package copypasta
/* 快速沃尔什变换 fast Walsh–Hadamard transform, FWT, FWHT
在算法竞赛中,FWT 是用于解决对下标进行【位运算卷积】问题的方法
一个常见的应用场景是对频率数组求 FWT
例如,求一个数组的三个元素的最大异或和,在值域不大的情况下,
例如把 a 里面所有元素的出现次数统计到一个 cnt 数组中,cnt[x] 表示 x 在 a 中的出现次数
然后求 FWT(cnt, cnt),就得到了 a 中任意两个元素的【异或/或/和】的结果的出现次数(特殊地,这得到了任意两个数的【异或/或/和】的最大值)
又例如,求一个数组的三个元素的最大异或和,在值域不大的情况下,
可以先求出该数组的频率数组与频率数组的 FWT,即得到两个元素的所有异或和(及组成该异或和的元素对数),
然后枚举两元素异或和,在原数组的异或字典树上查询最大异或和
具体到名称,OR 上的 FWT 也叫 fast zeta transform,AND 上的 FWT 也叫 fast mobius transform
https://en.wikipedia.org/wiki/Fast_Walsh%E2%80%93Hadamard_transform
https://oi-wiki.org/math/poly/fwt/
OR Convolution for Common People https://codeforces.com/blog/entry/115438
https://www.luogu.com.cn/blog/CJL/fwt-xue-xi-bi-ji
https://www.luogu.com.cn/blog/command-block/wei-yun-suan-juan-ji-yu-ji-kuo-zhan
一些习题 https://blog.csdn.net/weixin_38686780/article/details/81912853
Expand Down
3 changes: 2 additions & 1 deletion copypasta/mo.go
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,8 @@ func moOnTree(n, root, q int, g [][]int, vals []int) []int {
vis := make([]bool, n)
move := func(v int) {
x := vals[v]
if vis[v] = !vis[v]; vis[v] {
vis[v] = !vis[v]
if vis[v] {
if cnt[x] == 0 {
cc++
}
Expand Down
29 changes: 19 additions & 10 deletions copypasta/monotone_stack.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ https://cp-algorithms.com/data_structures/stack_queue_modification.html
- [496. 下一个更大元素 I](https://leetcode.cn/problems/next-greater-element-i/)(单调栈模板题)
- [503. 下一个更大元素 II](https://leetcode.cn/problems/next-greater-element-ii/)
- [2454. 下一个更大元素 IV](https://leetcode.cn/problems/next-greater-element-iv/)
- [456. 132 模式](https://leetcode.cn/problems/132-pattern/)
- [739. 每日温度](https://leetcode.cn/problems/daily-temperatures/)
- [901. 股票价格跨度](https://leetcode.cn/problems/online-stock-span/)
Expand Down Expand Up @@ -187,29 +188,37 @@ func monotoneStack(a []int) ([]int, []int) {

// 注:若输入的是一个 1~n 的排列,求两侧大于/小于位置有更简单的写法
// 用双向链表思考(代码实现时用的数组):
// - 把 p 转换成双向链表,按元素值**从小到大**遍历 p[i],那么 p[i] 左右两侧的就是大于 p[i] 的元素
// - 算完 p[i] 后把 p[i] 从链表中删掉
// 为简单起见,求出的下标从 1 开始(不存在时表示为 0 或 n+1)
// - 把 perm 转换成双向链表,按元素值**从小到大**遍历 perm[i],那么 perm[i] 左右两侧的就是大于 perm[i] 的元素
// - 算完 perm[i] 后把 perm[i] 从链表中删掉
// 为避免判断下标越界,传入的 perm 虽然下标是从 0 开始的,但视作从 1 开始(不存在时表示为 0 或 n+1)
// https://codeforces.com/contest/1156/problem/E
// https://atcoder.jp/contests/abc140/tasks/abc140_e
func permLR(p []int) ([]int, []int) {
n := len(p)
idx := make([]int, n+1)
func permLR(perm []int) ([]int, []int) {
n := len(perm)
pos := make([]int, n+1)
left := make([]int, n+2)
right := make([]int, n+1)
for i := 1; i <= n; i++ {
idx[p[i-1]] = i
pos[perm[i-1]] = i
left[i], right[i] = i-1, i+1
}
right[0] = 1
left[n+1] = n // 哨兵(本题不需要这两行,但是某些题目需要,比如 https://codeforces.com/problemset/problem/1154/E)
del := func(i int) {
l, r := left[i], right[i]
right[l] = r
left[r] = l
}

// 正序遍历求出的是两侧大于位置
// 倒序遍历求出的是两侧小于位置
for v := 1; v <= n; v++ {
i := idx[v]
i := pos[v]
l, r := left[i], right[i]
// do ...
_, _ = l, r

right[l] = r
left[r] = l // 删除 v
del(i) // 从链表中删除 v
}
return left, right
}
Expand Down
Loading

0 comments on commit bcfae0a

Please sign in to comment.