- 博客(17)
- 收藏
- 关注
原创 后缀数组模板
namespace SA{ int n, k, rk[MAXN], tmp[MAXN]; bool compare_sa(int i, int j) { if (rk[i] != rk[j]) return rk[i] < rk[j]; int ri = i + k <= n ? rk[i + k] : -1; // 注意是 <= n int rj = j + k <= n ? rk[j + k]
2021-06-06 16:16:12
115
原创 多重背包优化
朴素时间复杂度:O(nms)O(nms)O(nms),其中nnn为物品个数,mmm为总体积,sss为多重个数。二进制优化朴素的多重背包其实就是010101背包,只不过多循坏了几次。考虑将一个可用sss次的物品拆分为1,2,4,8,⋯ ,2k,s−2k−(2k−1)1, 2, 4, 8 ,\cdots, 2 ^ k, s - 2 ^ k - (2 ^ k - 1)1,2,4,8,⋯,2k,s−2k−(2k−1),这样就可以用不超过logs\log slogs个组成1∼s1 \sim s1∼s里的每一个
2021-05-30 10:32:01
212
原创 矩阵模板
const LL P = 1e9 + 7;typedef vector<LL> vec;typedef vector<vec> mat;void print(mat A){ rep(i, A.size()) { rep(j, A[0].size()) cout << A[i][j] << ' '; cout << endl; }}mat operator * (mat A, mat B)
2021-05-16 21:58:10
145
原创 强连通分量内路径基和环基
(模意义下&非简单路径&非简单环)名字是随便取的qwq强连通分量路径长的性质property1如果存在一条从uuu到vvv长为xxx的路径,就一定存在一条从vvv到uuu长为−x-x−x的路径。proof假设存在一条从vvv到uuu长为yyy的路径,那么就有一条y+x+y+x+y+⋯+x+y=(MOD−1)×x+MOD×y=−xy + x + y + x + y + \cdots + x + y = (MOD - 1) \times x + MOD \times y = -x
2021-05-05 20:45:31
225
原创 并查集维护邻边
在一些题目中需要不断地将一些点合并为一个点,同时也就带来了麻烦:如何高效地维护邻居集合?我们可以将邻边启发式合并,其复杂度可以做到O(mlogn)O(m \log n)O(mlogn)。具体来说,在访问时,从邻接表的末端向前扫描,如果边的两个端点已经在同一集合里,就将这条边删了。如此可以保证访问次数和边数基本相等。在合并两个点集时,将边数小的点集合并到边数大的点集里去,可以证明,该复杂度为O(mlogn)O(m \log n)O(mlogn)。几点注意操作时,我们只需要考虑各个集合的根,也就
2021-05-05 16:54:26
120
原创 归并树
归并树归并树是线段树的一种,它的每个节点都是一个数组,通常是按某一顺序将数组排好序,便于统计。每次区间操作只会涉及到O(logn)O(\log n)O(logn)个节点,排好序的数组又可以用二分查找来统计某个量,所以每次查询的复杂度通常为O(log2n)O(\log^2n)O(log2n)。int n, m, a[N], num[N];struct tnode{ vector<int> ver; tnode* lson,* rson; tnode
2021-04-22 21:28:57
543
原创 分块
平方分割和分桶法平方分割就是在维护一个数列上的某些信息时,通常将O(n)O(\sqrt{n})O(n)的元素分在一个桶内,分别维护每个桶内的信息。这样当我们查询某些信息时就可以分为桶内查询和逐个查询,由于桶的数目为O(n)O(\sqrt{n})O(n)级别的,逐个查询的复杂度也是O(n)O(\sqrt{n})O(n)级别的,于是就将O(n2)O(n^2)O(n2)降为了O(nn)O(n\sqrt{n})O(nn)。const int B = 1000;int n, m, a[N], num
2021-04-22 20:04:48
77
原创 树状数组模版
一维树状数组struct Fenwick{ LL d[N]; void init(){ rep(i, n + 1) d[i] = 0; } void modify(int x, LL val){ while (x <= n){ d[x] += val; x += x & -x; } } LL query(int x){ LL ret = 0; while (x){ ret += d[x]; x -= x & -x; } return ret; }
2021-04-21 20:42:38
75
原创 ST表模板
静态区间最大值rep(i, n) rmq[i][0] = a[i]; rep1(i, 18) rep(j, n) if (j + (1 << i) <= n) rmq[j][i] = max(rmq[j][i - 1], rmq[j + (1 << i - 1)][i - 1]); while (q --){ int l, r; scanf("%d%d", &l, &r); l --, r --; int i;
2021-04-20 21:37:18
61
原创 线段树模板
区间加线段树struct tnode{ LL val, add; tnode* lson,* rson; tnode(LL num = 0) { val = num; add = 0; lson = rson = NULL; } ~tnode() { if (lson) delete lson; if (rson) delete rson; } void maintain()
2021-04-20 20:10:11
101
原创 二进制枚举
枚举集合的子集for (int s = S; ; s = (s - 1) & S){ // do something if (!s) break;}枚举大小为k的子集int s = (1 << k) - 1;while (s < 1 << n){ // do something int x = s & -s, y = s + x; s = ((s & ~y) / x >> 1) | y
2021-04-19 20:29:47
120
原创 埃氏筛法
埃氏筛埃氏筛的原理就是每次在素数表中将素数ppp的倍数划去,实现简单。时间复杂度:O(nlogn)O(n\log n)O(nlogn)。空间复杂度:O(n)O(n)O(n)。int prime[N], kp;bool is_prime[N];void sieve(int k){ for (int i = 0; i <= k; ++ i) is_prime[i] = true; is_prime[0] = is_prime[1] = false; kp = 0;
2021-04-15 21:25:05
850
原创 欧几里得算法及其扩展
欧几里得算法在我读过的文献里,称其是“最古老的算法”之一。欧几里得算法是用来计算两个整数的最大公约数,其算法流程如下。int gcd(int a, int b){ return b == 0 ? a : gcd(b, a % b);}如果我们要来证明这个算法的正确性,通常需要找到一个在反复迭代中不变的量。并且这个不变的量和终止的条件b=0b = 0b=0能够说明函数所返回的就是gcd(a,b)\gcd(a, b)gcd(a,b)。找到一个不变的量通常是很困难的,因此我们首先要证明算法
2021-04-14 21:46:38
264
原创 最短路相关模型
严格次短路简洁明了,就是求图GGG中sss到ttt的次短路,不过它在长度上要严格大于最短路。我们维护两个数组,distidist_idisti表示sss到iii的最短距离,disti′dist'_idisti′表示sss到iii的严格次短距离,在图GGG上跑一遍sss到ttt的DijksgtraDijksgtraDijksgtra,每次更新距离时优先更新distidist_idisti,其次再更新disti′dist'_idisti′。其实次短距离(不一定比最短距离长)做法十分相似,稍微改一下
2021-04-13 21:34:59
126
原创 最小生成树算法
Prim算法PrimPrimPrim算法和DijkstraDijkstraDijkstra最短路算法十分相似。我们从111号节点出发,不断地向生成树里加最小权值边。假设我们已有一颗树TTT,满足TTT为一颗最小生成树的子图。令XXX为TTT的点集,eee为连接XXX和V∖XV\setminus XV∖X的最小权值边,我们要证明存在一棵生成树包含了TTT和eee。同样,假设包含TTT的最小生成树不包含eee,那么将eee加到这颗树里之后一定会形成一个环,且此时除eee以外还有另一条边fff连接着XXX和
2021-04-12 20:14:57
110
原创 最短路算法
Bellman-Ford算法适用范围:单源最短路,无负环,可以有负权。记从起点sss出发到节点iii的最短距离为did_idi,则下述等式成立。di=mine=(j,i)∈E{dj+len(j,i)}d_i = \min_{e = (j, i)\in E}\{d_j + len(j, i)\}di=e=(j,i)∈Emin{dj+len(j,i)}设初值ds=0d_s = 0ds=0,di=infd_i = \infdi=inf,不断利用这条递推关系式更新ddd的值,就可以算出新
2021-04-11 18:58:56
94
原创 强连通分量(dfs version)
强连通分量(dfs version)定义我们称有向图G=(V,E)G = (V, E)G=(V,E)是强连通的当且仅当对于GGG中任意两点u,vu, vu,v都存在一条uuu到vvv的路径和一条vvv到uuu的路径。如果G′G'G′为GGG的一个子图且G′G'G′是强连通的,则称G′G'G′是一个强连通子图。若G′G'G′满足极大性,则称G′G'G′是一个强连通分量。那么,如果我们将所有的强连通分量都缩成一个点,就可以得到一张DAGDAGDAG。因为如果存在环的话,就可以继续缩点。如何求强连通分量
2021-04-10 13:56:49
539
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人