大学打ACM时总结的一些常用数据结构和字符串算法的模板代码。主要包括树状数组、线段树、树链剖分、LCA、主席树、平衡树、树分治、CDQ分治等数据结构算法,和kmp、hash、manacher、pam、SA、SAM等字符串算法。
data structure
STL
bitset
1 | bitset<4> bs; |
pb-ds rbtree
不进行区间信息整合时,可用,优点是代码量少。注意常数极大。
1 |
|
pb_ds priority_queue
1 |
|
rope
2018牛客多校。序列翻转。
1 |
|
list
百度之星。合并两个链表。
1 |
|
nth_element
2018牛客多校第六场。$O(n)$
1 |
|
指针建树
二叉搜索树指针版
1 |
|
指针动态开点trie
1 | using namespace std; |
指针静态开点trie
1 | int t,n,a,ok; |
单调队列、单调栈
2019出题,利用单调性求出贡献区间。
1 |
|
树状数组
一维树状数组基础模板。
1 |
|
树状数组-全局第k大和排名
1 |
|
树状数组离线求区间不同数字个数
2018牛客多校第一场。
1 |
|
二维树状数组模板
1 | using namespace std; |
线段树
区间修改,区间求和模板
1 | using namespace std; |
标记永久化
1 | inline int cross(int L,int R,int l,int r){ |
and or max
1 |
|
二维线段树模板
1 |
|
权值线段树模板
1 | // luogu-judger-enable-o2 |
动态开点线段树
2019山东省赛。
1 |
|
势能线段树模板
1 |
|
线段合并问题
//pku campus, unsolved
1 |
|
扫描线求矩形面积并
1 |
|
扫描线求矩形周长并
1 | using namespace std; |
LCA
rmq版本的LCA。
1 |
|
倍增法求LCA
1 |
|
树链剖分求LCA
1 | struct edge{int nxt,to,v;}e[maxn<<1]; |
树链剖分
点权模板
luogu qtree3。
1 |
|
基于边权
1 | struct edge{int nxt,to,v;}e[maxn<<1]; |
虚树 东北四省赛D
1 |
|
主席树
省内存
1 | void update(int &u,int p,int l,int r){ |
可持久化
1 | const int maxn = 2e6+10; |
静态区间第k大
1 |
|
动态区间第k大,主席树+树状数组
1 |
|
树上区间第k大
1 |
|
区间修改历史版本线段树
1 |
|
平衡树
treap
1 |
|
splay copy from kuangbin
1 | /* |
树分治
引入
1 | /*题目:给一棵边权无根树,问是否有点对距离为k |
有多少点对距离不大于k
1 |
|
距离为3的倍数的点对数
1 |
|
CDQ分治
2018湖南省赛,线段覆盖问题。
1 |
|
三维偏序
1 | /* |
三维LIS
1 | /* |
长方体内点的数量
1 | /* |
可持久化并查集
1 |
|
带撤回的并查集
1 |
|
整体二分
静态区间第k小
1 |
|
动态区间第k小
1 | using namespace std; |
笛卡尔树
1 | /** |
字典树
01 trie
1 |
|
可持久化trie树
1 |
|
string
kmp
牛客多校带回退的kmp
1 | #include <bits/stdc++.h> |
hash
1 | typedef long long ll; |
manacher
南京现场赛manacher + exkmp
1 | #include <bits/stdc++.h> |
回文自动机
hdu多校第二场的回文串题 pam + hash
1 | #include<bits/stdc++.h> |
补充
1 | if(len[now]<=2)half[now]=fail[now]; |
后缀数组
sais
1 | #define ll long long |
下一位置不确定的SA做法
1 |
|
两串相同子串个数
1 | #include<bits/stdc++.h> |
AC自动机
1 | #include<bits/stdc++.h> |
SAM
最短不重复子串4合1
1 |
|
允许3次失配的子串匹配
1 | #include<bits/stdc++.h> |
第k小子串
1 | /**T为0则表示不同位置的相同子串算作一个。T=1则表示不同位置的相同子串算作多个**/ |
出现次数在[A,B]之间的子串个数
1 | int tmp=root; |
两串LCS
1 | for(int a=0;a<len;a++)sam(s[a]-'a'); |
多个串的LCS
1 |
|
区间[L,R]内不同子串个数
1 | inline void sam(int alp){ |
统计长度为[1..l]的子串最多出现次数
1 | int tmp=root; |
最小表示法
1 | int minpre(char s[]){ |