数据结构代码模板
这里记录了数据结构方面平时个人常用的代码模板。
数据结构
单调数据结构
- 数组某一个值作为区间极值的区间长度:单调栈处理L、R数组CF547B.
- 求$k$长限制下最大子段和:单调队列维护递增前缀和,P1714.
- 对数字保持相对顺序去重并使字典序最大:,Maximize the Remaining String.
单调栈求每一元素作为区间极值的端点
1 | int a[maxn],ans[maxn],stk[maxn],top=0,l[maxn],r[maxn]; |
对数字保持相对顺序去重并使字典序最大
1 | char s[maxn],stk[maxn]; |
树状数组
一种天才的数据结构,利用了二进制下标来控制区间范围,构造了一种类似二叉树的数据结构,使得空间复杂度仍为$O(n)$的情况下,对于区间前缀和的查询时间复杂度达到了$O(logn)$。
在树状数组中,每一个下标为$x$的节点,都保存着在$[x-2^k+1,x]$的区间和,$k$为$x$二进制末尾$0$的个数。
可进行区间修改区间查询的bit模板
和单点修改并查询前缀和的实现思路略有不同。
1 | struct BinaryIndexedsTree |
二维树状数组
1 | struct BinaryIndexedsTree2D |
三维树状数组求前缀最大值
1 | struct BinaryIndexTree |
树状数组实现平衡树
1 | struct BITth |
01字典树
1 | class Trie01 |
普通线段树
1 | struct SegTreeForMax |
动态开点线段树
该模板的区间推平操作有问题,请尽量避免使用assign
。
1 | struct SegTree |
可持久化权值线段树
1 |
|
替罪羊树
1 | const int maxn=1E5+5; |
AVL树
1 | struct Node |
Splay
1 | const int maxn=2e5+10,inf=0x3f3f3f3f,mod=1000000007; |
lzy发过来的
1 |
|
Link Cut Tree
这个数据结构可以建立点与点的间接关系与直接关系——可以查询一个点的权值,以及两点是否在同一棵树中,同时对已经连边的两点,切断本来已经有的连边。
$init():$ 用之前先初始化一下,同时注意 $MAXN$ 到底是多少。
$clear():$ 将所有的节点清空。
$haveEdge(x,y):$ 若之前 $x$ 和 $y$ $link()$ 过,则返回 $true$,否则返回 $false$。
$find(x):$ 找到 $x$ 所属树的编号。
$link(x,y):$ 将 $x$ 和 $y$ 连边,前提是 $find(x)!=find(y)$ 。
$cut(x,y):$ 将 $x$ 和 $y$ 之间的边隔断,前提是 $haveEdge(x,y)$ 为 $true$。
一开始赋值的时候给 $sz2[]$ 赋值为初值。
每个操作一次的时间复杂度大概是 $O(logn)$。
1 | struct lctNode |
1044 数树
来源:https://codeforces.com/contest/1277/problem/E
$tag:$ LCT
离散化
题目大意
给出一些有标号的点 $x(1≤x≤10^8)$,共有三种操作:
- 将 $u$ 和 $v$ 连起来。
- 将 $u$ 和 $v$ 之间的连边删除。
- 询问大小不为 $1$ 的树的个数。
输入中可能添加重边,也可能删除不存在的边,略过就好,保证不被忽略的操作 $1$ 不构成环。
题目样例
样例输入
1 | 4 |
样例输出
1 | 1 |
样例解释
一共有 $4$ 个操作,第一个操作将 $1926$ 和 $817$ 连边,第二个操作询问,输出 $1$ ,第三个操作删除 $1926$ 和 $817$ 的连边,第四个操作询问,输出 $0$。
题目解法
先把询问存起来,离线离散化一波,然后建一棵 $LCT$。$1$ 操作实质上就是 $link$, $2$ 操作实质上就是 $cut$,考虑维护答案 $ans$ 为大小不为 $1$ 的树,则对于操作 $1$:
- 若两个大小为 $1$ 的节点 $link$ 一下就会变成一棵大小为 $2$ 的树,所以 $ans++$。
- 若两棵大小都不为 $1$,$link$ 一下就会变成一棵大小不为 $1$ 的树,所以 $ans–$。
- 若两棵树一棵大小为 $1$ ,一棵不为 $1$ ,则 $link$ 后答案不变。
对于操作 $2$ 同理,对于操作 $3$ 输出 $ans$即可。
时间复杂度 $O(nlogn)$。
完整代码
1 | /*Hatsune Miku 4ever!*/ |
珂朵莉树
1 | struct ChthollyTree |
左偏树
在保持二叉堆基础性质上可以快速合并的堆
定义
外节点:左右儿子不完整的节点
距离:最近的外节点到该点的距离
性质
节点权值不大于左右儿子权值(堆性质)
节点左儿子距离≥右儿子距离(左偏性质)
节点距离=右儿子距离+1
P3377 【模板】左偏树(可并堆)
一开始有 n 个小根堆,每个堆包含且仅包含一个数。接下来需要支持两种操作:
1 x y
:将第 x 个数和第 y 个数所在的小根堆合并(若第 x 或第 y 个数已经被删除或第 x 和第 y 个数在用一个堆内,则无视此操作)。2 x
:输出第 x 个数所在的堆最小数,并将这个最小数删除(若有多个最小数,优先删除先输入的;若第 x 个数已经被删除,则输出 -1 并无视删除操作)。
1 | struct LeftistTree |
P1552 [APIO2012]派遣
在一棵树上,每个点有点权$w$与倍率$l$,有限制$m$,要求一棵子树选择点的点权和不超过$m$。使得子树根节点倍率$l$乘以树上可选择节点数目最大。
思路:枚举每个点作为根,只要在子树中权值最小的点选起使权值之和小于$m$,可以递归地使用堆合并。
1 | struct LeftistTree |
ST表
1 | const int maxn=100005; |
分块
区间众数
1 | const int maxn=40005,lim=205,inf=0x3f3f3f3f; |
莫队
时刻注意桶是否越界。
例题
1 | struct block |