观前须知

Sugar_Cube的博客园主页

声明

本文所有内容遵循CC BY-NC-SA 4.0 Deed原则

本文包含了笔者常用的OI算法、数据结构的模板

不保证算法最优,但能通过相应的模板题(如果有会挂出)

如有错误请在评论区指出(虽然大抵没人看就是了)

码风是笔者的个人习惯(能看懂就好喵)

代码会省略快读Read()

持续更新

咕咕咕

输入输出优化

快读

inline int Read() {
int res = 0;
bool flag = false;
int c = getchar();
//~c防止EOF读到-1而卡死循环,一般情况可省略
while ((c < '0' || c > '9') && ~c) {
flag |= c == '-';
c = getchar();
}
while (c >= '0' && c <= '9') {
res = (res << 1) + (res << 3) + (c ^ 48);
c = getchar();
}
return flag ? -res : res;
}

浮点数快读

typedef long double ld;

inline ld Read() {
ld res = 0;
bool flag = false;
int c = getchar();
while ((c < '0' || c > '9') && ~c) {
flag |= c == '-';
c = getchar();
}
while (c >= '0' && c <= '9') {
res = res * 10 + (c ^ 48);
c = getchar();
}
if (c == '.') {
c = getchar();
ld f = 1;
while (c >= '0' && c <= '9') {
f /= 10;
res += f * (c ^ 48);
c = getchar();
}
}
return flag ? -res : res;
}

数据结构

树状数组

Luogu P3374 【模板】树状数组 1

constexpr int AwA = 5e5 + 10;

int n, m;
int a[AwA];
int c[AwA]; inline void Update(int idx, int x) {
while (idx <= n) {
c[idx] += x;
idx += idx & -idx;
}
} inline int Query(int idx) {
int res = 0;
while (idx) {
res += c[idx];
idx -= idx & -idx;
}
return res;
} int main() {
n = Read(), m = Read();
//根据树状数组定义O(n)建树
for (int i = 1; i <= n; i++) a[i] = a[i - 1] + Read();
for (int i = 1; i <= n; i++) c[i] = a[i] - a[i - (i & -i)]; while (m--) {
int op = Read(), x = Read(), y = Read();
if (op == 1) Update(x, y);
else printf("%d\n", Query(y) - Query(x - 1));
} return 0;
}

ST表

Luogu P3865 【模板】ST表

constexpr int AwA = 1e5 + 10;
constexpr int QwQ = 21; int n, m;
int f[AwA][QwQ], a[AwA]; inline void PreST() {
for (int i = 1; i <= n; i++) f[i][0] = a[i];
for (int j = 1; j <= __lg(n); j++)
for (int i = 1; i + (1 << j) - 1 <= n; i++)
f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
} inline int Query(int l, int r) {
int k = __lg(r - l + 1);
return max(f[l][k], f[r - (1 << k) + 1][k]);
} int main() {
n = Read(), m = Read();
for (int i = 1; i <= n; i++) a[i] = Read();
PreST();
while (m--) {
int l = Read(), r = Read();
printf("%d\n", Query(l, r));
}
return 0;
}

线段树

Luogu P3373 【模板】线段树2

#include<bits/stdc++.h>

using namespace std;

inline static int Read() {
int res = 0;
bool flag = false;
int c = getchar();
while ((c < '0' || c > '9') && ~c) {
flag |= c == '-';
c = getchar();
}
while (c >= '0' && c <= '9') {
res = (res << 1) + (res << 3) + (c ^ 48);
c = getchar();
}
return flag ? -res : res;
} static constexpr int AwA = 1e5 + 10; int n, Mod, Q;
int a[AwA];
//不动态开点的线段树要开4倍数组
struct Node {
int mul_tag, add_tag;
int sum;
} tr[AwA << 2]; inline void PushUp(int u) {
//线段树的左右儿子分别为2*u,2*u+1
tr[u].sum = (tr[u << 1].sum + tr[u << 1 | 1].sum) % Mod;
} //本棵线段树最重要的一个函数
inline void PushDown(int u, int l, int r) {
int lc = u << 1, rc = u << 1 | 1, mid = (l + r) >> 1;
if (tr[u].mul_tag != 1) {
tr[lc].mul_tag = int(1ll * tr[lc].mul_tag * tr[u].mul_tag % Mod);
tr[lc].add_tag = int(1ll * tr[lc].add_tag * tr[u].mul_tag % Mod);
tr[lc].sum = int(1ll * tr[lc].sum * tr[u].mul_tag % Mod);
tr[rc].mul_tag = int(1ll * tr[rc].mul_tag * tr[u].mul_tag % Mod);
tr[rc].add_tag = int(1ll * tr[rc].add_tag * tr[u].mul_tag % Mod);
tr[rc].sum = int(1ll * tr[rc].sum * tr[u].mul_tag % Mod);
tr[u].mul_tag = 1;
}
if (tr[u].add_tag) {
tr[lc].add_tag = (tr[lc].add_tag + tr[u].add_tag) % Mod;
tr[lc].sum = int((tr[lc].sum + 1ll * tr[u].add_tag * (mid - l + 1)) % Mod);
tr[rc].add_tag = (tr[rc].add_tag + tr[u].add_tag) % Mod;
tr[rc].sum = int((tr[rc].sum + 1ll * tr[u].add_tag * (r - mid)) % Mod);
tr[u].add_tag = 0;
}
} //O(n)建树
void Build(int u, int l, int r) {
tr[u] = {1, 0, 0};
if (l == r) return void(tr[u].sum = a[l]);
int mid = (l + r) >> 1;
Build(u << 1, l, mid);
Build(u << 1 | 1, mid + 1, r);
PushUp(u);
} void UpdateMul(int u, int l, int r, int lx, int rx, int val) {
if (lx <= l && r <= rx) {
tr[u].sum = int(1ll * tr[u].sum * val % Mod);
tr[u].mul_tag = int(1ll * tr[u].mul_tag * val % Mod);
tr[u].add_tag = int(1ll * tr[u].add_tag * val % Mod);
return;
}
PushDown(u, l, r);
int mid = (l + r) >> 1;
if (lx <= mid) UpdateMul(u << 1, l, mid, lx, rx, val);
if (mid + 1 <= rx) UpdateMul(u << 1 | 1, mid + 1, r, lx, rx, val);
PushUp(u);
} void UpdateAdd(int u, int l, int r, int lx, int rx, int val) {
if (lx <= l && r <= rx) {
tr[u].sum = int((1ll * val * (r - l + 1) + tr[u].sum) % Mod);
tr[u].add_tag = (tr[u].add_tag + val) % Mod;
return;
}
PushDown(u, l, r);
int mid = (l + r) >> 1;
if (lx <= mid) UpdateAdd(u << 1, l, mid, lx, rx, val);
if (mid + 1 <= rx) UpdateAdd(u << 1 | 1, mid + 1, r, lx, rx, val);
PushUp(u);
} int Query(int u, int l, int r, int lx, int rx) {
if (lx <= l && r <= rx) return tr[u].sum;
PushDown(u, l, r);
int mid = (l + r) >> 1, res = 0;
if (lx <= mid) res = (res + Query(u << 1, l, mid, lx, rx)) % Mod;
if (mid + 1 <= rx) res = (res + Query(u << 1 | 1, mid + 1, r, lx, rx)) % Mod;
return res;
} int main() {
n = Read(), Q = Read(), Mod = Read();
for (int i = 1; i <= n; i++) a[i] = Read();
Build(1, 1, n);
while (Q--) {
int op = Read();
if (op == 1) {
int l = Read(), r = Read(), val = Read();
UpdateMul(1, 1, n, l, r, val % Mod);
} else if (op == 2) {
int l = Read(), r = Read(), val = Read();
UpdateAdd(1, 1, n, l, r, val % Mod);
} else {
int l = Read(), r = Read();
printf("%d\n", Query(1, 1, n, l, r));
}
}
return 0;
}

FHQ Treap

Luogu P3369 普通平衡树

constexpr int AwA = 1e6 + 10;

//生成随机数
mt19937 rd{random_device()()}; struct Node {
int lc, rc, sz;
int val;
//mt19937 返回uint类型
unsigned int rd;
} tr[AwA]; int rt, tot; inline int NewNode(int _val) {
tr[++tot] = {0, 0, 1, _val, rd()};
return tot;
} inline void PushUp(int u) {
tr[u].sz = tr[tr[u].lc].sz + tr[tr[u].rc].sz + 1;
} void SplitVal(int u, int val, int &x, int &y) {
//压行.jpg
if (!u) return void(x = y = 0);
if (tr[u].val <= val) {
x = u;
SplitVal(tr[u].rc, val, tr[x].rc, y);
} else {
y = u;
SplitVal(tr[u].lc, val, x, tr[y].lc);
}
PushUp(u);
} int Merge(int x, int y) {
if (!x || !y) return x | y;
if (tr[x].rd <= tr[y].rd) {
tr[x].rc = Merge(tr[x].rc, y);
PushUp(x);
return x;
}
tr[y].lc = Merge(x, tr[y].lc);
PushUp(y);
return y;
} inline void Insert(int _val) {
int x, y;
SplitVal(rt, _val, x, y);
rt = Merge(Merge(x, NewNode(_val)), y);
} int main() {
int Q = Read();
while (Q--) {
int op = Read(), v = Read();
if (op == 1) Insert(v);
else if (op == 2) {
int x, y, z;
SplitVal(rt, v, x, z);
SplitVal(x, v - 1, x, y);
y = Merge(tr[y].lc, tr[y].rc);
rt = Merge(Merge(x, y), z);
} else if (op == 3) {
int x, y;
SplitVal(rt, v - 1, x, y);
printf("%d\n", tr[x].sz + 1);
rt = Merge(x, y);
} else if (op == 4) {
int u = rt;
while (true) {
int sz = tr[tr[u].lc].sz + 1;
if (sz == v) break;
else if (sz > v) u = tr[u].lc;
else u = tr[u].rc, v -= sz;
}
printf("%d\n", tr[u].val);
} else if (op == 5) {
int x, y;
SplitVal(rt, v - 1, x, y);
int u = x;
while (tr[u].rc) u = tr[u].rc;
rt = Merge(x, y);
printf("%d\n", tr[u].val);
} else {
int x, y;
SplitVal(rt, v, x, y);
int u = y;
while (tr[u].lc) u = tr[u].lc;
rt = Merge(x, y);
printf("%d\n", tr[u].val);
}
}
return 0;
}

FHQ Treap 文艺平衡树

Luogu P3391 文艺平衡树

constexpr int AwA = 1e5 + 10;

mt19937 rd{random_device()()};

struct Node {
int lc, rc, sz;
int val;
unsigned int rd;
bool revTag;
} tr[AwA]; int rt, tot; inline int NewNode(int _val) {
tr[++tot] = {0, 0, 1, _val, rd(), false};
return tot;
} inline void PushUp(int u) {
tr[u].sz = tr[tr[u].lc].sz + tr[tr[u].rc].sz + 1;
} inline void PushDown(int u) {
if (!tr[u].revTag) return;
swap(tr[u].lc, tr[u].rc);
if (tr[u].lc) tr[tr[u].lc].revTag ^= 1;
if (tr[u].rc) tr[tr[u].rc].revTag ^= 1;
tr[u].revTag = false;
} void SplitSz(int u, int sz, int &x, int &y) {
if (!u) return void(x = y = 0);
PushDown(u);
if (tr[tr[u].lc].sz + 1 <= sz) {
x = u;
SplitSz(tr[u].rc, sz - tr[tr[u].lc].sz - 1, tr[x].rc, y);
} else {
y = u;
SplitSz(tr[u].lc, sz, x, tr[y].lc);
}
PushUp(u);
} int Merge(int x, int y) {
if (!x || !y) return x | y;
if (tr[x].rd <= tr[y].rd) {
PushDown(x);
tr[x].rc = Merge(tr[x].rc, y);
PushUp(x);
return x;
}
PushDown(y);
tr[y].lc = Merge(x, tr[y].lc);
PushUp(y);
return y;
} inline void Build(int n) {
for (int i = 1; i <= n; i++) NewNode(i);
static int stk[AwA], top;
stk[top = 1] = 1;
for (int i = 2; i <= n; i++) {
int tmp = 0;
while (top && tr[stk[top]].rd > tr[i].rd) PushUp(tmp = stk[top--]);
if (top) tr[stk[top]].rc = i;
if (tmp) tr[i].lc = tmp;
stk[++top] = i;
}
for (int i = top; i; i--) PushUp(i);
rt = stk[1];
} void Print(int u) {
if (!u) return;
PushDown(u);
Print(tr[u].lc);
printf("%d ", tr[u].val);
Print(tr[u].rc);
} int main() {
int n = Read(), Q = Read();
Build(n);
while (Q--) {
int l = Read(), r = Read();
int x, y, z;
SplitSz(rt, r, x, z);
SplitSz(x, l - 1, x, y);
tr[y].revTag ^= 1;
rt = Merge(Merge(x, y), z);
}
Print(rt);
putchar('\n');
return 0;
}

块状链表

因为笔者暂时没有POJ账号所以模板题先咕咕咕喵

static constexpr int QwQ = 1e3;

struct Node {
int nxt, sz;
int a[(QwQ << 1) + 10]; inline void Insert(int pos, int val) {
for (int i = sz; i >= pos; i--) a[i + 1] = a[i];
a[pos] = val;
sz++;
} inline void Delete(int pos) {
for (int i = pos; i < sz; i++) a[i] = a[i + 1];
sz--;
}
} t[QwQ + 10]; int tcnt = 1; inline void Check(int u) {
if (t[u].sz < QwQ << 1) return;
int v = ++tcnt;
t[v].nxt = t[u].nxt;
t[u].nxt = v;
t[v].sz = t[u].sz - QwQ;
for (int i = 1; i <= t[v].sz; i++) t[v].a[i] = t[u].a[i + QwQ];
t[u].sz = QwQ;
} inline void Insert(int pos, int val) {
int u;
for (u = 1; t[u].nxt && t[u].sz < pos; pos -= t[u].sz, u = t[u].nxt);
t[u].Insert(min(pos, t[u].sz + 1), val);
Check(u);
} inline int Query(int pos) {
int u;
for (u = 1; t[u].nxt && t[u].sz < pos; pos -= t[u].sz, u = t[u].nxt);
return t[u].a[pos];
} inline void Delete(int pos) {
int u;
for (u = 1; t[u].nxt && t[u].sz < pos; pos -= t[u].sz, u = t[u].nxt);
t[u].Delete(pos);
}

图论

树上问题

倍增LCA

Luogu P3379 【模板】最近公共祖先(LCA)

constexpr int AwA = 5e5 + 10;
constexpr int QwQ = 21; struct Edge {
int nxt, v;
} e[AwA << 1];
int head[AwA], ecnt; inline void AddEdge(int u, int v) {
e[++ecnt] = {head[u], v};
head[u] = ecnt;
} int n, m, rt;
int fa[AwA][QwQ], dep[AwA]; void Dfs(int u, int _fa) {
fa[u][0] = _fa;
dep[u] = dep[fa[u][0]] + 1;
for (int j = 0; j < __lg(dep[u]); fa[u][j + 1] = fa[fa[u][j]][j], j++);
for (int i = head[u]; i; i = e[i].nxt) if (e[i].v != fa[u][0]) Dfs(e[i].v, u);
} inline int LCA(int x, int y) {
if (dep[x] < dep[y]) swap(x, y);
for (int i = __lg(dep[x] - dep[y]); ~i; i--)
if (dep[fa[x][i]] >= dep[y]) x = fa[x][i];
if (x == y) return x;
for (int i = __lg(dep[x]); ~i; i--)
if (fa[x][i] != fa[y][i])
x = fa[x][i], y = fa[y][i];
return fa[x][0];
} int main() {
n = Read(), m = Read(), rt = Read();
for (int i = 1; i < n; i++) {
int u = Read(), v = Read();
AddEdge(u, v);
AddEdge(v, u);
} Dfs(rt, 0);
while (m--) printf("%d\n", LCA(Read(), Read()));
return 0;
}

欧拉序lca

Luogu P3379 【模板】最近公共祖先(LCA)

constexpr int AwA = 5e5 + 10;
constexpr int QwQ = 22; struct Edge {
int nxt, v;
} e[AwA << 1];
int head[AwA], ecnt; inline void AddEdge(int u, int v) {
e[++ecnt] = {head[u], v};
head[u] = ecnt;
} int n, m, rt;
int dep[AwA], dfn[AwA], idfn[AwA << 1];
int f[AwA << 1][QwQ], g[AwA << 1][QwQ]; void Dfs(int u, int fa = 0) {
dep[u] = dep[fa] + 1;
idfn[++idfn[0]] = u;
dfn[u] = idfn[0];
for (int i = head[u]; i; i = e[i].nxt)
if (e[i].v != fa) Dfs(e[i].v, u), idfn[++idfn[0]] = u;
} inline void InitST() {
for (int i = 1; i <= idfn[0]; i++) f[i][0] = dep[idfn[i]], g[i][0] = idfn[i];
for (int j = 1; j <= __lg(idfn[0]); j++)
for (int i = 1; i + (1 << j) - 1 <= idfn[0]; i++) {
f[i][j] = min(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]);
if (f[i][j - 1] < f[i + (1 << (j - 1))][j - 1]) g[i][j] = g[i][j - 1];
else g[i][j] = g[i + (1 << (j - 1))][j - 1];
}
} inline int QueryMnPos(int l, int r) {
int k = __lg(r - l + 1);
if (f[l][k] < f[r - (1 << k) + 1][k]) return g[l][k];
return g[r - (1 << k) + 1][k];
} inline int LCA(int x, int y) {
int l = dfn[x], r = dfn[y];
if (l > r) swap(l, r);
return QueryMnPos(l, r);
} int main() {
n = Read(), m = Read(), rt = Read();
for (int i = 1; i < n; i++) {
int u = Read(), v = Read();
AddEdge(u, v);
AddEdge(v, u);
} Dfs(rt);
InitST();
while (m--) printf("%d\n", LCA(Read(), Read()));
return 0;
}

树链剖分

P3384 【模板】重链剖分/树链剖分

typedef long long ll;
constexpr int AwA = 1e5 + 10; struct Edge {
int nxt, v;
} e[AwA << 1];
int head[AwA], ecnt; inline void AddEdge(int u, int v) {
e[++ecnt] = {head[u], v};
head[u] = ecnt;
e[++ecnt] = {head[v], u};
head[v] = ecnt;
} int n, m, rt, Mod;
ll sum[AwA << 2], tag[AwA << 2];
int sz[AwA], son[AwA], fa[AwA], top[AwA], dfn[AwA], dep[AwA];
int a[AwA]; void Update(int u, int l, int r, int lx, int rx, int val) {
if (l == lx && r == rx) {
tag[u] += val;
tag[u] %= Mod;
return;
}
sum[u] += 1ll * val * (rx - lx + 1);
sum[u] %= Mod;
int mid = (l + r) >> 1;
if (lx <= mid) Update(u << 1, l, mid, lx, min(mid, rx), val);
if (mid + 1 <= rx) Update(u << 1 | 1, mid + 1, r, max(lx, mid + 1), rx, val);
} ll Query(int u, int l, int r, int lx, int rx) {
ll res = tag[u] * (rx - lx + 1);
if (lx == l && r == rx) return (res + sum[u]) % Mod;
int mid = (l + r) >> 1;
if (lx <= mid) res += Query(u << 1, l, mid, lx, min(mid, rx));
if (mid + 1 <= rx) res += Query(u << 1 | 1, mid + 1, r, max(mid + 1, lx), rx);
return res % Mod;
} void Dfs1(int u, int _fa) {
sz[u] = 1;
fa[u] = _fa;
dep[u] = dep[fa[u]] + 1;
for (int i = head[u]; i; i = e[i].nxt)
if (e[i].v != fa[u]) {
int v = e[i].v;
Dfs1(v, u);
if (sz[v] > sz[son[u]]) son[u] = v;
sz[u] += sz[v];
}
} void Dfs2(int u, int _top) {
top[u] = _top;
dfn[u] = ++dfn[0];
if (son[u]) Dfs2(son[u], top[u]);
for (int i = head[u]; i; i = e[i].nxt)
if (e[i].v != fa[u] && e[i].v != son[u]) Dfs2(e[i].v, e[i].v);
} inline void UpdatePath(int val, int x, int y) {
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
Update(1, 1, n, dfn[top[x]], dfn[x], val);
x = fa[top[x]];
}
if (dep[x] < dep[y]) swap(x, y);
Update(1, 1, n, dfn[y], dfn[x], val);
} inline ll QueryPath(int x, int y) {
ll res = 0;
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
res += Query(1, 1, n, dfn[top[x]], dfn[x]);
x = fa[top[x]];
}
if (dep[x] < dep[y]) swap(x, y);
res += Query(1, 1, n, dfn[y], dfn[x]);
return res % Mod;
} int main() {
n = Read(), m = Read(), rt = Read(), Mod = Read();
for (int i = 1; i <= n; i++) a[i] = Read();
for (int i = 1; i < n; i++) AddEdge(Read(), Read());
Dfs1(rt, 0);
Dfs2(rt, rt);
for (int i = 1; i <= n; i++) Update(1, 1, n, dfn[i], dfn[i], a[i]); while (m--) {
int op = Read();
if (op == 1) UpdatePath(Read(), Read(), Read());
else if (op == 2) printf("%lld\n", QueryPath(Read(), Read()));
else if (op == 3) {
int u = Read(), v = Read();
Update(1, 1, n, dfn[u], dfn[u] + sz[u] - 1, v);
} else {
int u = Read();
printf("%lld\n", Query(1, 1, n, dfn[u], dfn[u] + sz[u] - 1));
}
}
return 0;
}

动态规划

01背包

P1048 【NOIP2005 普及组】 采药

constexpr int AwA = 1e2 + 10;
constexpr int QwQ = 1e3 + 10; int n, m;
int v[AwA], w[AwA];
int f[QwQ]; int main() {
m = Read(), n = Read();
for (int i = 1; i <= n; i++) v[i] = Read(), w[i] = Read();
//这里枚举j要倒序
for (int i = 1; i <= n; i++)
for (int j = m; j >= v[i]; j--)
f[j] = max(f[j], f[j - v[i]] + w[i]);
printf("%d\n", f[m]);
return 0;
}

完全背包

没找到模板题抱歉喵~

constexpr int AwA = 1e2 + 10;
constexpr int QwQ = 1e3 + 10; int n, m;
int v[AwA], w[AwA];
int f[QwQ]; int main() {
m = Read(), n = Read();
for (int i = 1; i <= n; i++) v[i] = Read(), w[i] = Read();
//这里枚举j要正序,这是和01背包唯一的一个区别
for (int i = 1; i <= n; i++)
for (int j = m; j >= v[i]; j--)
f[j] = max(f[j], f[j - v[i]] + w[i]);
printf("%d\n", f[m]);
return 0;
}

字符串

哈希

Luogu P3370 【模板】字符串哈希

constexpr int AwA = 1e4 + 10;

struct Hash {
static constexpr int Mod1 = 1e9 + 7;
static constexpr int Mod2 = 1e9 + 9;
static constexpr int P = 131; //双哈希
int h1, h2; //空构造为默认构造
Hash() = default; //将给定的字符串视为一个P进制数计算哈希值
Hash(const char *s) {
//默认字符串数组下标从1开始
h1 = h2 = 0;
int len = int(strlen(s + 1));
for (int i = 1; i <= len; i++) {
h1 = int((1ll * h1 * P + s[i]) % Mod1);
h2 = int((1ll * h2 * P + s[i]) % Mod2);
}
} //sort要用,使相等的哈希相邻
inline bool operator<(const Hash &hh) const {
return h1 < hh.h1 || (h1 == hh.h1 && h2 < hh.h2);
} //unique要用,当且仅当两个哈希值都相等认为两个字符串相等
inline bool operator==(const Hash &hh) const {
return h1 == hh.h1 && h2 == hh.h2;
}
} h[AwA]; int n;
char s[AwA]; int main() {
n = Read();
for (int i = 1; i <= n; i++) {
scanf("%s", s + 1);
h[i] = Hash(s);
} sort(h + 1, h + n + 1);
int ans = int(unique(h + 1, h + n + 1) - h - 1);
printf("%d\n", ans);
return 0;
}

哈希表

Luogu P3370 【模板】字符串哈希

typedef unsigned long long ull;
static constexpr int P = 131;
static constexpr int AwA = 1e4 + 10; class HashTable {
private:
//笔者常用的哈希表质数
static constexpr int Mod = 1e6 + 3; struct Node {
int nxt;
ull val;
} p[AwA];
int head[Mod], pcnt;
public:
inline void Clear() {
memset(head, 0, sizeof head);
pcnt = 0;
} //若待插入的数已在哈希表中返回false,否则插入
inline bool Insert(ull val) {
if (Find(val)) return false;
int hs = int(val % Mod);
p[++pcnt] = {head[hs], val};
head[hs] = pcnt;
return true;
} //查找当前的数是否已在哈希表中
inline bool Find(ull val) {
int hs = int(val % Mod);
for (int i = head[hs]; i; i = p[i].nxt)
if (p[i].val == val) return true;
//未找到
return false;
}
} mp; inline ull Hash(const char *s) {
ull h = 0;
int len = int(strlen(s + 1));
//自然溢出,即模2的64次方
for (int i = 1; i <= len; i++) h = h * P + s[i];
return h;
} int n, ans;
char s[AwA]; int main() {
n = Read();
for (int i = 1; i <= n; i++) {
scanf("%s", s + 1);
if (mp.Insert(Hash(s))) ans++;
}
printf("%d\n", ans);
return 0;
}

KMP

Luogu P3375 【模板】KMP

constexpr int AwA = 1e6 + 10;

int n, m;
char s1[AwA], s2[AwA];
int p[AwA]; inline void Pre() {
p[1] = 0;
for (int i = 2, j = 0; i <= m; i++) {
while (j && s2[j + 1] != s2[i]) j = p[j];
if (s2[j + 1] == s2[i]) j++;
p[i] = j;
}
} inline void Kmp() {
for (int i = 1, j = 0; i <= n; i++) {
while (j && s2[j + 1] != s1[i]) j = p[j];
if (s2[j + 1] == s1[i]) j++;
if (j == m) printf("%d\n", i - m + 1), j = p[j];
}
} int main() {
scanf("%s%s", s1 + 1, s2 + 1);
n = int(strlen(s1 + 1)), m = int(strlen(s2 + 1)); Pre();
Kmp(); for (int i = 1; i <= m; i++) printf("%d ", p[i]);
putchar('\n');
return 0;
}

Trie树

Luogu P8306 【模板】字典树

constexpr int AwA = 3e6 + 10;

struct Node {
int ch[62];
int cnt;
} tr[AwA]; int tot;
char s[AwA]; inline int CharToInt(char c) {
if (c <= '9') return c - '0' + 52;
if (c >= 'a') return c - 'a' + 26;
return c - 'A';
} inline int NewNode() {
tot++;
memset(tr[tot].ch, 0, sizeof(int) * 62);
tr[tot].cnt = 0;
return tot;
} inline void Insert() {
int u = 1, len = int(strlen(s + 1));
for (int i = 1; i <= len; i++) {
int c = CharToInt(s[i]);
if (!tr[u].ch[c]) tr[u].ch[c] = NewNode();
u = tr[u].ch[c];
tr[u].cnt++;
}
} int main() {
int T = Read();
while (T--) {
tot = 0;
NewNode(); int n = Read(), m = Read();
for (int i = 1; i <= n; i++) {
scanf("%s", s + 1);
Insert();
} while (m--) {
scanf("%s", s + 1);
int u = 1, len = int(strlen(s + 1));
for (int i = 1; i <= len && u; i++) {
int c = CharToInt(s[i]);
u = tr[u].ch[c];
}
printf("%d\n", tr[u].cnt);
}
} return 0;
}

Manacher

Luogu P3805 【模板】manacher

static constexpr int AwA = 1.1e7 + 10;

int m, n;
//两个数组注意开2倍
char s1[AwA], s[AwA << 1];
int d[AwA << 1];
int ans; int main() {
scanf("%s", s1 + 1);
m = int(strlen(s1 + 1)); //处理字符串
n = 2 * m + 1;
s[0] = '?', s[1] = '#';
for (int i = 1; i <= m; i++) {
s[i * 2] = s1[i];
s[i * 2 + 1] = '#';
}
s[n + 1] = '\0'; d[1] = 1;
for (int i = 2, l = 1, r = 1; i <= n; i++) {
if (i <= r) d[i] = min(r - i + 1, d[r - i + l]);
while (s[i + d[i]] == s[i - d[i]]) d[i]++;
if (i + d[i] - 1 >= r) r = i + d[i] - 1, l = i - d[i] + 1;
} //回文子串长度=处理后的回文半径-1
for (int i = 1; i <= n; i++) ans = max(ans, d[i] - 1);
printf("%d\n", ans);
return 0;
}

数学

矩阵快速幂

P3390 【模板】矩阵快速幂

常用的矩阵操作基本都放在这里了喵

typedef long long ll;
constexpr int AwA = 1e2 + 10;
constexpr int Mod = 1e9 + 7; class Matrix {
private:
//n是行数,m是列数
int n, m;
ll a[AwA][AwA]; public:
Matrix() = default; Matrix(int n, int m) : n(n), m(m) { memset(a, 0, sizeof a); } //方便调用
inline ll *operator[](int x) { return a[x]; } //-同理不写了
inline Matrix operator+(Matrix &m1) const {
Matrix res(n, m);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
res[i][j] = (a[i][j] + m1[i][j]) % Mod;
return res;
} inline Matrix operator*(Matrix &m1) const {
int q = m1.m;
ll r;
Matrix res(n, q);
//换枚举方式减小常数
for (int i = 1; i <= n; i++)
for (int k = 1; k <= m; k++) {
r = a[i][k];
for (int j = 1; j <= q; j++)
res[i][j] = (res[i][j] + r * m1[k][j]) % Mod;
}
return res;
} inline Matrix operator^(ll k) const {
Matrix res(n, n);
for (int i = 1; i <= n; i++) res[i][i] = 1;
Matrix b(n, n);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
b[i][j] = a[i][j]; while (k) {
if (k & 1) res = res * b;
b = b * b;
k >>= 1;
}
return res;
}
}; int main() {
int n = Read();
ll k = Read<ll>(); Matrix a(n, n);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
a[i][j] = Read(); Matrix res = a ^ k;
for (int i = 1; i <= n; i++, putchar('\n'))
for (int j = 1; j <= n; j++)
printf("%lld ", res[i][j]); return 0;
}

SC的板子库~的更多相关文章

  1. 【转】uvm 与 system verilog的理解

    http://www.cnblogs.com/loves6036/p/5779691.html 数字芯片和FPGA的验证.主要是其中的功能仿真和时序仿真. 验证中通常要搭建一个完整的测试平台和写所需要 ...

  2. FPGA验证之SystemVerilog+UVM

    [转载]https://blog.csdn.net/lijiuyangzilsc/article/details/50879545     数字芯片和FPGA的验证.主要是其中的功能仿真和时序仿真. ...

  3. 安装linux各种桌面环境

    1.安装kde ①添加 KDE SC 4.11 库 打开一个终端窗口,在终端窗口中输入如下命令: sudo add-apt-repository ppa:kubuntu-ppa/backports 回 ...

  4. JSTL标签库之核心标签

    一.JSTL标签库介绍 JSTL标签库的使用是为弥补html标签的不足,规范自定义标签的使用而诞生的.使用JSLT标签的目的就是不希望在jsp页面中出现java逻辑代码 二.JSTL标签库的分类 核心 ...

  5. 初涉java库--ArrayList

    我的车就差一个轮子啦,造好轮子,我就飞上天与太阳肩并肩啦,想想都激动.什么你要自己造轮子,是不是傻,商店里不都是别人造好的吗,又好又方便,只需一点money,你没有money,那你只能做个安静的美男子 ...

  6. 【MCU】【STM32】1.cube MX库使用笔记

    STM32Cube 是一个全面的软件平台,包括了ST产品的每个系列.(如,STM32CubeF4 是针对STM32F4系列). 平台包括了STM32Cube 硬件抽象层和一套的中间件组件(RTOS, ...

  7. 六轴加速度传感器MPU6050官方DMP库到瑞萨RL78/G13的移植

    2015年的电赛已经结束了.赛前接到器件清单的时候,看到带防护圈的多旋翼飞行器赫然在列,又给了一个瑞萨RL78/G13的MCU,于是自然联想到13年的电赛,觉得多半是拿RL78/G13做四旋翼的主控, ...

  8. 24 个你应该了解的 PHP 库

    24 个你应该了解的 PHP 库 2015-09-08    分类:WEB开发.编程开发.首页精华暂无人评论     来源:伯乐在线 分享到:更多3 二十万年薪PHP工程师培养计划 成为被疯抢的And ...

  9. 树莓派wiringPi库详解

    wiringPi是一个很棒的树莓派IO控制库,使用C语言开发,提供了丰富的接口:GPIO控制,中断,多线程,等等.java 的pi4j项目也是基于wiringPi的,我最近也在看源代码,到时候整理好了 ...

  10. Auty自动化测试框架第五篇——框架内部的调用支持、自动化安装库与配置说明

    [本文出自天外归云的博客园] 本次对Auty自动化测试框架做些收尾工作,由于在scripts文件夹中的脚本会需要调用其他包结构文件夹中的脚本,所以这里需要添加一下框架对于内部脚本间互相调用的支持,这里 ...

随机推荐

  1. docker 常用命令 快捷命令

    一.查询节点 docker ps -a 二.docker重启停止 systemctl restart docker systemctl stop docker docker restart * 三.一 ...

  2. maketrans和translate按规则一次性替换多个字符,用来替代replace

    str_ = 'i love you' compiler_ = str_.maketrans('i l y', 'I L Y') print(str_.translate(compiler_))

  3. 【Azure 服务总线】查看Service Bus中消息多次发送的日志信息,消息是否被重复消费

    问题描述 使用Service Bus,发现消息被重复消费.如果要查看某一条消息的具体消费情况,需要那些消息的属性呢? 问题解答 使用Azure Service Bus,当消费发送到服务端后,就会生产相 ...

  4. Autofac入门与替代ASP.NET Core、ABP依赖注入容器

    目录 Autofac 的使用 1,简单的实践 2,注册组件 3,Lambda 注册组件 4,注册泛型 5,属性注入 6,解析服务 7,生命周期 8,实例作用域 9,Autofac 其它需要学习的知识 ...

  5. D3.js 力导向图的显示优化(二)- 自定义功能

    摘要: 在本文中,我们将借助 D3.js 的灵活性这一优势,去新增一些 D3.js 本身并不支持但我们想要的一些常见的功能:Nebula Graph 图探索的删除节点和缩放功能. 文章首发于 Nebu ...

  6. Redis单线程为什么如此之快

    一.概述 Redis的高并发和快简单可以归结为一下几点: 1.Redis是基于内存的: 2.Redis是单线程的: 3.Redis使用多路复用技术. 4.高效的数据结构 但具体怎么做的呢,下面来详细看 ...

  7. JAVA 多线程---面经

    线程与进程 提到进程那就要说程序,程序有指令和数据,程序从磁盘加载到内存,cpu获得指令进行执行,其中还会用到各种资源如网络资源,磁盘等.一个程序从磁盘进入内存,就是进程实例的创建. 一个程序可以有多 ...

  8. GitLab (v16.x) 简述及安装部署

    GitLab 介绍 GitLab 的历史 GitLab 最初是一个完全免费的开源软件,根据 MIT 许可证分发.2013 年 7 月,它被分为两个不同的版本 - GitLab CE(社区版)和 Git ...

  9. 关于Sql server数据类型HierarchyID 数据类型用法和递归显示完整路径

    SQL Server 2008版本之后的新类型HierarchyID 不知道大家有没有了解, 该类型作为取代id, parentid的一种解决方案,让人非常惊喜. 官方给的案例浅显易懂,但是没有实现我 ...

  10. linux下find命令根据系统时间查找文件用法

    find 命令有几个用于根据您系统的时间戳搜索文件的选项.这些时间戳包括 mtime 文件内容上次修改时间 atime 文件被读取或访问的时间 ctime 文件状态变化时间 mtime 和 atime ...