模板库
策略
第一步
Check List:(B-ALIVE)
- ⭐️
Border:调不出来一定记得检查所有边界!!! Array:数组大小别开错(翻 \(k\) 倍、双向边开两倍等)Long:long long(1ll << x)、mmul的1llInit:多测(滚动)数组要清空、忌用memset,单测也要记得初始化数组Value:树状数组等数据结构的范围(权值上的)Exceed:小心MLE、TLE- 'Define':尝试还原宏定义
第二步
Prepare:
- Theme
- Auto-save
- Clap
- Snippets
- init
- edge
- mod
- read/write
- segtree
- disjointset
- dinic
第三步(10min)
读题,读数据范围,模拟样例。
第四步(50min)
从简单到难,想所有题。
- 观察性质
- 大胆猜测
- 简化性质
- 构造双射
想正解;如果没有头绪就一定要想暴力。
验证解法正确性、细节、时间复杂度
记录做法、分数。
第五步(3h)
写题。不能超过 1h。超过就写下一个。
\(Think\ twice, code\ ONCE!\)
基本
Linux_share
sudo mount -t fuse.vmhgfs-fuse .host:/ /mnt/hgfs -o allow_other
Sublime Text 编译器初始化
{
"shell_cmd": "g++ -std=c++14 -Wall -O2 \"${file}\" -o \"${file_path}/${file_base_name}\"",
"file_regex": "^(..[^:]*):([0-9]+):?([0-9]+)?:? (.*)$",
"working_dir": "${file_path}",
"selector": "source.c++",
"variants":
[
{
"name": "Run",
"shell_cmd": "g++ -std=c++14 -Wall -O2 \"${file}\" -o \"${file_path}/${file_base_name}\" && \"${file_path}/${file_base_name}\""
}
]
}
必背
init
// Author: Aquizahv
#include <bits/stdc++.h>
using namespace std;
// #include <bits/extc++.h>
// using namespace __gnu_pbds;
#define For(i, x, y) for (int i = x; i <= y; i++)
#define Rof(i, x, y) for (int i = x; i >= y; i--)
using ll = long long;
using pii = pair<int, int>;
const int N = ;
int main()
{
freopen(".in", "r", stdin);
freopen(".out", "w", stdout);
}
fastio
int read()
{
bool f = 1; int x = 0;
char ch = getchar();
while (ch < '0' || ch > '9')
{ if (ch == '-') f = !f; ch = getchar(); }
while (ch >= '0' && ch <= '9')
{ x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar(); }
return f ? x : -x;
}
void write(int x)
{
if (x < 0)
{
putchar('-');
x = -x;
}
if (x > 9)
write(x / 10);
putchar((x % 10) ^ 48);
}
mod
int A(int x, int y) { return x + y >= MOD ? x + y - MOD : x + y; }
int A(initializer_list<int> t) { int res = 0;
for (auto i : t) res = A(res, i); return res; }
void SA(int &x, int y) { x = A(x, y); }
int S(int x, int y) { return A(x, MOD - y); }
int W(int x, int y) { return 1ll * x * y % MOD; }
int W(initializer_list<int> t) { int res = 1;
for (auto i : t) res = W(res, i); return res; }
void SW(int &x, int y) { x = W(x, y); }
int P(int x, int y) { int res = 1, t = x % MOD;
while (y) { if (y & 1) res = W(res, t);
t = W(t, t); y >>= 1; }
return res; }
int D(int x, int y) { return W(x, P(y, MOD - 2)); }
int Q(int x) { return W(x, x); }
pb_ds
__gnu_pbds::tree<pii, __gnu_pbds::null_type, less<pii>, __gnu_pbds::rb_tree_tag, __gnu_pbds::tree_order_statistics_node_update> s[N];
clap
// Author: Aquizahv
#include <bits/stdc++.h>
using namespace std;
int main()
{
for (int i = 1; i <= 10000; i++)
{
cout << "Case #" << i << endl;
system("./data");
system("./bf");
system("./my");
if (system("diff bf.out my.out"))
return 0;
}
return 0;
}
数学
数论
Exgcd
int exgcd(int a, int b, int &x, int &y)
{
if (b == 0)
{
x = 1, y = 0;
return a;
}
int d = exgcd(b, a % b, y, x);
y -= (a / b) * x;
return d;
}
CRT(不如 ExCRT)
// https://www.luogu.com.cn/problem/P1495
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N = 15;
int n, x[N], X = 1, y[N], z[N], ans;
int exgcd(int a, int b, int &x, int &y)
{
if (b == 0)
{
x = 1, y = 0;
return a;
}
int d = exgcd(b, a % b, y, x);
y -= (a / b) * x;
return d;
}
int inv(int a, int b)
{
int x, y;
exgcd(a, b, x, y);
return (x % b + b) % b;
}
int mmul(int x, int y, int p)
{
int res = 0, t = x % p;
while (y)
{
if (y & 1)
res = (res + t) % p;
t = (t + t) % p;
y >>= 1;
}
return res;
}
signed main()
{
#ifdef aquazhao
freopen("data.in", "r", stdin);
// freopen("data.out", "w", stdout);
#endif
cin >> n;
for (int i = 1; i <= n; i++)
{
scanf("%lld%lld", x + i, y + i);
X *= x[i];
}
for (int i = 1; i <= n; i++)
{
int tmp = X / x[i];
z[i] = tmp * inv(tmp, x[i]);
ans = (ans + mmul(y[i] % X, z[i] % X, X)) % X;
}
cout << ans << endl;
return 0;
}
ExCRT
// Author: Aquizahv
#include <bits/stdc++.h>
#define ll __int128
#define inf 0x3f3f3f3f
#define lnf 0x3f3f3f3f3f3f3f3f
using namespace std;
const int N = 1e5 + 5;
int n;
ll a[N], b[N];
inline void write(ll x)
{
if (x < 0)
{
putchar('-');
x = -x;
}
if (x > 9)
write(x / 10);
putchar((x % 10) ^ 48);
}
ll exgcd(ll a, ll b, ll &x, ll &y)
{
if (b == 0)
{
x = 1, y = 0;
return a;
}
ll d = exgcd(b, a % b, y, x);
y -= (a / b) * x;
return d;
}
ll solve(ll &x, ll a, ll b, ll c)
{
ll y;
ll d = exgcd(a, b, x, y);
if (c % d)
{
puts("AbsoluTe disoRdeR");
exit(0);
}
x *= c / d;
ll p = b / d;
x = (x % p + p) % p;
return d;
}
ll excrt()
{
for (int i = 2; i <= n; i++)
{
ll x;
ll d = solve(x, a[1], a[i], b[i] - b[1]);
b[1] = (x * a[1] + b[1]) % (a[1] * a[i] / d);
a[1] = a[1] * a[i] / d;
}
return b[1];
}
int main()
{
#ifdef Aquizahv
freopen("data.in", "r", stdin);
freopen("data.out", "w", stdout);
#endif
cin >> n;
long long x, y;
for (int i = 1; i <= n; i++)
scanf("%lld%lld", &x, &y), a[i] = x, b[i] = y;
write(excrt());
return 0;
}
Lucas
int C(int x, int y)
{
线性代数
高斯消元
// https://www.luogu.com.cn/problem/P3389
#include <bits/stdc++.h>
using namespace std;
const int N = 105;
int n;
double a[N][N], ans[N];
const double eps = 1e-7;
int main()
{
#ifdef aquazhao
freopen("data.in", "r", stdin);
// freopen("data.out", "w", stdout);
#endif
cin >> n;
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n + 1; j++)
scanf("%lf", &a[i][j]);
for (int i = 1; i <= n; i++)
{
int r = i;
for (int j = i + 1; j <= n; j++)
if (fabs(a[r][i]) < fabs(a[j][i]))
r = j;
if (fabs(a[r][i]) < eps)
{
puts("No Solution");
return 0;
}
if (i != r)
swap(a[i], a[r]);
double d = a[i][i];
for (int j = i; j <= n + 1; j++)
a[i][j] /= d;
for (int j = i + 1; j <= n; j++)
{
d = a[j][i];
for (int k = i; k <= n + 1; k++)
a[j][k] -= a[i][k] * d;
}
}
ans[n] = a[n][n + 1];
for (int i = n - 1; i >= 1; i--)
{
ans[i] = a[i][n + 1];
for (int j = i + 1; j <= n; j++)
ans[i] -= a[i][j] * ans[j];
}
for (int i = 1; i <= n; i++)
printf("%.2lf\n", ans[i]);
return 0;
}
线性基
const int N = 100, w = 30;
int n, s, a[N];
void insert(int x)
{
for (int k = w; k >= 0; k--)
if (x & (1 << k))
{
if (a[k] == 0)
{
a[k] = x;
return;
}
else
x ^= a[k];
}
}
int qmax()
{
int res = 0;
for (int k = w; k >= 0; k--)
res = max(res, res ^ a[k]);
return res;
}
树论
点分治
int sz[N], dp[N];
bool vis[N];
pii getroot(int u, int fa, int Sz)
{
pii res = {inf, 0};
dp[u] = sz[u] = 1;
for (auto v : e[u])
if (v != fa && !vis[v])
{
res = min(res, getroot(v, u, Sz));
sz[u] += sz[v];
dp[u] = max(dp[u], sz[v]);
}
return min(res, {max(dp[u], Sz - sz[u]), u});
}
void cal(int u)
{
//
}
void starch(int u)
{
cal(u);
vis[u] = true;
for (auto v : e[u])
if (!vis[v])
starch(getroot(v, 0, sz[v]).second);
}
图论
最短路
Floyd
for (int k = 1; k <= n; k++)
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
Dijkstra
void Dijkstra(int st)
{
memset(dis, 0x3f, sizeof(dis));
memset(vis, 0, sizeof(vis));
dis[st] = 0;
priority_queue<int> q;
q.push(st);
while (!q.empty())
{
int u = q.top();
q.pop();
if (vis[u])
continue;
vis[u] = true;
for (int i = head[u]; i; i = e[i].next)
{
int v = e[i].v, w = e[i].w;
if (dis[v] > dis[u] + w)
{
dis[v] = dis[u] + w;
q.push(v);
}
}
}
}
Bellman Ford
void BellmanFord(int st)
{
memset(dis, 0x3f, sizeof(dis));
dis[st] = 0;
for (int k = 1; k <= n; k++)
for (int i = 1; i <= pos; i++)
dis[e[i].v] = min(dis[e[i].v], dis[e[i].u] + e[i].w);
}
SPFA
void SPFA(int s)
{
memset(vis, 0, sizeof(vis));
memset(dis, 0x3f, sizeof(dis));
dis[s] = 0;
queue<int> q;
q.push(s);
while (q.size())
{
int u = q.front();
q.pop();
vis[u] = false;
for (int i = head[u]; i; i = e[i].next)
{
int v = e[i].v, w = e[i].w;
if (dis[v] > dis[u] + w)
{
dis[v] = dis[u] + w;
if (!vis[v])
vis[v] = true, q.push(v);
}
}
}
}
Tarjan
强连通分量
int dfn[N], low[N], dfncnt, stk[N], tp;
bool instk[N];
int scccnt, id[N], sz[N];
vector<int> scc[N];
void tarjan(int u)
{
dfn[u] = low[u] = ++dfncnt;
stk[++tp] = u;
instk[u] = true;
for (int v : g[u])
{
if (!dfn[v])
{
tarjan(v);
low[u] = min(low[u], low[v]);
}
else if (instk[v])
low[u] = min(low[u], dfn[v]);
}
if (low[u] == dfn[u])
{
int v;
scccnt++;
do
{
v = stk[tp--];
instk[v] = false;
id[v] = scccnt;
scc[scccnt].push_back(v);
sz[scccnt]++;
} while (v != u);
}
}
割边
int dfncnt, dfn[N], low[N];
void tarjan(int u, int fa)
{
dfn[u] = low[u] = ++dfncnt;
for (int i = head[u]; i; i = e[i].nxt)
{
int v = e[i].v;
if (!dfn[v])
{
tarjan(v, u);
low[u] = min(low[u], low[v]);
if (low[v] > dfn[u])
bridge[i] = bridge[i ^ 1] = true;
}
else if (v != fa && dfn[v] < dfn[u])
low[u] = min(low[u], dfn[v]);
}
}
割点(圆方树)
int dfncnt, dfn[N], low[N], stk[N], tp;
bool instk[N];
int bcccnt, id[N];
int tarjan(int u, int fa)
{
int res = 1, son = 0;
dfn[u] = low[u] = ++dfncnt;
stk[++tp] = u;
for (int i = head[u]; i; i = e[i].nxt)
{
int v = e[i].v;
if (!dfn[v])
{
son++;
res += tarjan(v, u);
low[u] = min(low[u], low[v]);
if (low[v] >= dfn[u])
{
bcccnt++;
int x;
do
{
x = stk[tp--];
id[x] = bcccnt;
addEdge2(n + bcccnt, x);
} while (x != v);
addEdge2(n + bcccnt, u);
}
}
else if (v != fa)
low[u] = min(low[u], dfn[v]);
}
if (!fa && !son)
{
bcccnt++;
addEdge2(n + bcccnt, u);
}
return res;
}
数据结构
并查集
struct disjoint_set
{
int f[N];
void init(int lmt)
{
for (int i = 1; i <= lmt; i++)
f[i] = i;
}
int find(int u)
{
if (f[u] == u)
return u;
return f[u] = find(f[u]);
}
bool merge(int u, int v)
{
int x = find(u), y = find(v);
if (x == y)
return false;
f[x] = y;
return true;
}
} ds;
线段树
线段树(单点加、区间加;区间 $\max$)
#define lson u + u
#define rson u + u + 1
int mx[ND], tag[ND];
void pushup(int u)
{
mx[u] = max(mx[lson], mx[rson]);
}
void add(int u, int x)
{
mx[u] += x;
tag[u] += x;
}
void pushdown(int u)
{
if (!tag[u])
return;
add(lson, tag[u]);
add(rson, tag[u]);
tag[u] = 0;
}
void update(int u, int l, int r, int it, int x)
{
if (l == r)
{
mx[u] += x;
return;
}
pushdown(u);
int mid = (l + r) >> 1;
if (it <= mid)
update1(lson, l, mid, it, x);
else
update1(rson, mid + 1, r, it, x);
pushup(u);
}
void update2(int u, int l, int r, int L, int R, int x)
{
if (L <= l && r <= R)
{
add(u, x);
return;
}
if (R < l || r < L)
return;
pushdown(u);
int mid = (l + r) >> 1;
update2(lson, l, mid, L, R, x);
update2(rson, mid + 1, r, L, R, x);
pushup(u);
}
int query(int u, int l, int r, int L, int R)
{
if (L <= l && r <= R)
return mx[u];
if (R < l || r < L)
return -inf;
pushdown(u);
int mid = (l + r) >> 1;
return max(query(lson, l, mid, L, R), query(rson, mid + 1, r, L, R));
}
动态开点线段树(单点加、区间加;区间 $\max$)
#define lson son[u][0]
#define rson son[u][1]
int tot = 1, son[ND][2], mx[ND], tag[ND];
void pushup(int u)
{
mx[u] = max(mx[lson], mx[rson]);
}
void add(int u, int x)
{
tag[u] += x;
mx[u] += x;
}
void pushdown(int u)
{
if (!lson)
lson = ++tot;
if (!rson)
rson = ++tot;
if (!tag[u])
return;
add(lson, tag[u]);
add(rson, tag[u]);
tag[u] = 0;
}
void update1(int u, int l, int r, int it, int x)
{
if (l == r)
{
mx[u] += x;
return;
}
pushdown(u);
int mid = (l + r) >> 1;
if (it <= mid)
update1(lson, l, mid, it, x);
else
update1(rson, mid + 1, r, it, x);
pushup(u);
}
void update2(int u, int l, int r, int L, int R, int x)
{
if (L <= l && r <= R)
{
add(u, x);
return;
}
if (R < l || r < L)
return;
pushdown(u);
int mid = (l + r) >> 1;
update2(lson, l, mid, L, R, x);
update2(rson, mid + 1, r, L, R, x);
pushup(u);
}
int query(int u, int l, int r, int L, int R)
{
if (L <= l && r <= R)
return mx[u];
if (R < l || r < L)
return -inf;
pushdown(u);
int mid = (l + r) >> 1;
return max(query(lson, l, mid, L, R), query(rson, mid + 1, r, L, R));
}
主席树(单点加;区间 $\max$)
int tot, son[ND][2], mx[ND];
void pushup(int u)
{
mx[u] = max(mx[son[u][0]], mx[son[u][1]]);
}
int update(int v, int l, int r, int it, int x)
{
int u = ++tot;
mx[u] = mx[v];
son[u][0] = son[v][0], son[u][1] = son[v][1];
if (l == r)
{
mx[u] += x;
return u;
}
int mid = (l + r) >> 1;
if (it <= mid)
son[u][0] = update(son[u][0], l, mid, it, x);
else
son[u][1] = update(son[u][1], mid + 1, r, it, x);
pushup(u);
return u;
}
int query(int u, int l, int r, int L, int R)
{
if (L <= l && r <= R)
return mx[u];
if (R < l || r < L)
return -inf;
int mid = (l + r) >> 1;
return max(query(son[u][0], l, mid, L, R), query(son[u][1], mid + 1, r, L, R));
}
主席树(lazytag)(区间加;区间 $\max$)
int tot, son[ND][2], tag[ND], mx[ND];
void pushup(int u)
{
mx[u] = max(mx[son[u][0]], mx[son[u][1]]);
}
void copy(int u, int v)
{
son[u][0] = son[v][0], son[u][1] = son[v][1];
tag[u] = tag[v], mx[u] = mx[v];
}
void add(int u, int x)
{
mx[u] += x;
tag[u] += x;
}
void pushdown(int u)
{
int lson = ++tot, rson = ++tot;
copy(lson, son[u][0]), copy(rson, son[u][1]);
son[u][0] = lson, son[u][1] = rson;
if (!tag[u])
return;
add(son[u][0], tag[u]);
add(son[u][1], tag[u]);
tag[u] = 0;
}
void update(int u, int l, int r, int L, int R, int x)
{
if (L <= l && r <= R)
{
mx[u] += x;
return;
}
if (R < l || r < L)
return;
pushdown(u);
int mid = (l + r) >> 1;
update(son[u][0], l, mid, L, R, x);
update(son[u][1], mid + 1, r, L, R, x);
pushup(u);
}
int query(int u, int l, int r, int L, int R)
{
if (L <= l && r <= R)
return mx[u];
if (R < l || r < L)
return -inf;
pushdown(u);
int mid = (l + r) >> 1;
return max(query(son[u][0], l, mid, L, R), query(son[u][1], mid + 1, r, L, R));
}
int main()
{
int root, root2 = ++tot;
// update
copy(root2, root);
update(root2, 1, n, l, r, x);
int root3 = ++tot;
// query
cout << query(root3, 1, n, l, r) << endl;
return 0;
}
平衡树
无旋 Treap
// 支持插入、删除、分裂、合并、查询第 k 大、查询 rank 等。
int son[N][2], val[N], rank[N], sz[N];
int build(int x)
{
int u = ++tot;
sz[u] = 1, val[u] = x, rank[u] = rand();
return u;
}
void pushup(int u)
{
sz[u] = sz[lson] + 1 + sz[rson];
}
void split(int u, int key, int &x, int &y) // x <= key, y > key
{
if (!u) { x = y = 0; return; }
if (val[u] <= key)
x = u, split(rson, key, rson, y);
else
y = u, split(lson, key, x, lson);
pushup(u);
}
void split2(int u, int key, int &x, int &y) // sz[x] == key
{
if (!u) { x = y = 0; return; }
if (sz[lson] < key)
x = u, split(rson, key - sz[lson] - 1, rson, y);
else
y = u, split(lson, key, x, lson);
pushup(u);
}
int merge(int u, int v)
{
if (!u || !v) return u ^ v;
if (rank[u] > rank[v])
{
rson = merge(rson, v);
pushup(u); return u;
}
else
{
son[v][0] = merge(u, son[v][0]);
pushup(v); return v;
}
}
void insert(int key)
{
int x, y;
split(root, key, x, y);
root = merge(merge(x, build(key)), y);
}
void erase(int key)
{
int x, y, z;
split(root, key, x, z);
split(x, key - 1, x, y);
y = merge(son[y][0], son[y][1]);
root = merge(merge(x, y), z);
}
树剖
重链剖分
int fa[N], sz[N], son[N], deep[N], top[N], dfncnt, dfn[N], dfd[N], dfx[N];
void dfs1(int u, int dep)
{
sz[u] = 1;
deep[u] = dep;
for (int v : g[u])
if (v != fa[u])
{
fa[v] = u;
dfs1(v, dep + 1);
sz[u] += sz[v];
if (sz[v] > sz[son[u]])
son[u] = v;
}
}
void dfs2(int u, int anc)
{
dfn[u] = ++dfncnt;
dfx[dfncnt] = u;
top[u] = anc;
if (son[u])
{
dfs2(son[u], anc);
for (int v : g[u])
if (v != fa[u] && v != son[u])
dfs2(v, v);
}
dfd[u] = dfncnt;
}
struct segtree
{
int sum[ND], tag[ND], len[ND];
void pushup(int u)
{
sum[u] = sum[lson] + sum[rson];
}
void pushdown(int u)
{
if (!tag[u])
return;
add(lson, tag[u]);
add(rson, tag[u]);
tag[u] = 0;
}
void add(int u, int x)
{
sum[u] += len[u] * x;
tag[u] += x;
}
void build(int u, int l, int r)
{
len[u] = r - l + 1;
if (l == r)
{
sum[u] = a[dfx[l]];
return;
}
int mid = (l + r) >> 1;
build(lson, l, mid);
build(rson, mid + 1, r);
pushup(u);
}
void update(int u, int l, int r, int L, int R, int x)
{
if (L <= l && r <= R)
{
add(u, x);
return;
}
if (R < l || r < L)
return;
pushdown(u);
int mid = (l + r) >> 1;
update(lson, l, mid, L, R, x);
update(rson, mid + 1, r, L, R, x);
pushup(u);
}
int query(int u, int l, int r, int L, int R)
{
if (L <= l && r <= R)
return sum[u];
if (R < l || r < L)
return 0;
pushdown(u);
int mid = (l + r) >> 1;
return query(lson, l, mid, L, R) + query(rson, mid + 1, r, L, R);
}
} t;
void path_add(int u, int v, int x)
{
while (top[u] != top[v])
{
if (deep[top[u]] < deep[top[v]])
swap(u, v);
t.update(1, 1, n, dfn[top[u]], dfn[u], x);
u = fa[top[u]];
}
if (deep[u] < deep[v])
swap(u, v);
t.update(1, 1, n, dfn[v], dfn[u], x);
}
int path_sum(int u, int v)
{
int res = 0;
while (top[u] != top[v])
{
if (deep[top[u]] < deep[top[v]])
swap(u, v);
res += t.query(1, 1, n, dfn[top[u]], dfn[u]);
u = fa[top[u]];
}
if (deep[u] < deep[v])
swap(u, v);
return res + t.query(1, 1, n, dfn[v], dfn[u]);
}
字符串
KMP
const int N = 1e6 + 5;
int n, m;
int nxt[N]; // t串前缀的border长度
char s[N], t[N];
int main()
{
scanf("%s%s", s + 1, t + 1);
n = strlen(s + 1);
m = strlen(t + 1);
for (int i = 2; i <= m; i++)
{
int j = nxt[i - 1];
while (j > 0 && t[i] != t[j + 1])
j = nxt[j];
if (t[i] == t[j + 1])
nxt[i] = j + 1;
}
for (int i = 1, j = 0; i <= n; i++)
{
while (j > 0 && s[i] != t[j + 1])
j = nxt[j];
if (s[i] == t[j + 1])
j++;
if (j == m)
printf("%d\n", i - m + 1);
}
for (int i = 1; i <= m; i++)
printf("%d%c", nxt[i], " \n"[i == m]);
return 0;
}
AC 自动机
// Author: Aquizahv
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 2e5 + 5, S = 2e6 + 5;
int n, ans[N];
char s[S], t[N];
struct AC_auto
{
int root = 1, tot = root, trie[N][30], fail[N], tag[N];
vector<int> id[N], g[N];
void insert(int cnt)
{
int pos = strlen(t + 1), u = root;
for (int i = 1; i <= pos; i++)
{
int d = t[i] - 'a';
if (!trie[u][d])
trie[u][d] = ++tot;
u = trie[u][d];
}
id[u].push_back(cnt);
}
void init_fail()
{
queue<int> q;
q.push(root);
fail[root] = root;
while (!q.empty())
{
int u = q.front();
q.pop();
for (int i = 0; i < 26; i++)
{
if (!trie[u][i])
trie[u][i] = u == root ? 1 : trie[fail[u]][i];
else
{
fail[trie[u][i]] = u == root ? root : trie[fail[u]][i];
g[fail[trie[u][i]]].push_back(trie[u][i]);
q.push(trie[u][i]);
}
}
}
}
void Pair()
{
int pos = strlen(s + 1);
int u = root;
for (int i = 1; i <= pos; i++)
{
u = trie[u][s[i] - 'a'];
tag[u]++;
}
}
int dfs(int u)
{
int res = tag[u];
for (int v : g[u])
res += dfs(v);
for (int i : id[u])
ans[i] = res;
return res;
}
void debug(int u)
{
for (int i = 0; i < 26; i++)
if (trie[u][i])
{
cout << u << ' ' << char('a' + i) << ' ' << trie[u][i] << endl;
debug(trie[u][i]);
}
}
} ac;
SA
struct SA
{
int n, s[N], sa[N], rk[N], sa2[N], _rk[N], cnt[N], h[N];
void build(int m)
{
for (int i = 1; i <= n; i++)
cnt[rk[i] = s[i]]++;
for (int i = 1; i <= m; i++)
cnt[i] += cnt[i - 1];
for (int i = n; i >= 1; i--)
sa[cnt[rk[i]]--] = i;
for (int w = 1, p = 0; p != n; m = p, w <<= 1)
{
int pos = 0;
for (int i = n - w + 1; i <= n; i++)
sa2[++pos] = i;
for (int i = 1; i <= n; i++)
if (sa[i] > w)
sa2[++pos] = sa[i] - w;
memset(cnt, 0, sizeof(cnt));
for (int i = 1; i <= n; i++)
cnt[rk[i]]++;
for (int i = 1; i <= m; i++)
cnt[i] += cnt[i - 1];
for (int i = n; i >= 1; i--)
sa[cnt[rk[sa2[i]]]--] = sa2[i];
memcpy(_rk, rk, sizeof(rk));
p = 0;
for (int i = 1; i <= n; i++)
{
if (_rk[sa[i]] == _rk[sa[i - 1]] && _rk[sa[i] + w] == _rk[sa[i - 1] + w])
rk[sa[i]] = p;
else
rk[sa[i]] = ++p;
}
}
for (int i = 1, k = 0; i <= n; i++)
{
if (rk[i] == 1)
continue;
k = max(k - 1, 0);
while (s[i + k] == s[sa[rk[i] - 1] + k])
k++;
h[rk[i]] = k;
}
}
};
杂项
SA
struct node
{
//
node operator*(const double T) const
{
//
}
} ans;
node cal(node cur, double T)
{
node res;
//
if (res.w < ans.w)
ans = res;
}
double Rand() { return (double)rand() / RAND_MAX; }
void SA()
{
double T = 100000;
node cur = ans, nxt;
while (T > 0.001)
{
nxt = cal(cur, T);
double delta = nxt.w - cur.w;
if (exp(-delta / T) > Rand())
cur = nxt;
T *= 0.99;
}
for (int i = 1; i <= 1000; i++)
cal(cur, T);
}
const double TL = 1;
int main()
{
#ifdef Aquizahv
freopen("data.in", "r", stdin);
freopen("data.out", "w", stdout);
#endif
srand(time(0));
while ((double)clock() / CLOCKS_PER_SEC < TL)
SA();
}
高精度
int t[LEN];
const int k = 10;
struct bignum
{
int len, a[LEN], op;
bignum() { len = 0, memset(a, 0, sizeof(a)), op = 1; }
void init(int x)
{
if (x < 0)
op = -1, x = -x;
while (x)
{
a[++len] = x % k;
x /= k;
}
}
void read()
{
char ch = getchar();
while (ch < '0' || ch > '9')
{ if (ch == '-') op *= -1; ch = getchar(); }
while (ch >= '0' && ch <= '9')
{ t[++len] = ch ^ 48; ch = getchar(); }
for (int i = 1; i <= len; i++)
a[i] = t[len - i + 1];
if (len == 1 && a[1] == 0)
len = 0;
}
void write()
{
if (op == -1)
putchar('-');
if (len == 0)
putchar('0');
for (int i = len; i >= 1; i--)
putchar(a[i] ^ 48);
}
bool operator<(const bignum t) const
{
if (op * t.op == -1)
return op < t.op;
int res = 0;
if (op == -1)
res = 1;
if (len != t.len)
return res ^ (len < t.len);
for (int i = len; i >= 1; i--)
if (a[i] != t.a[i])
return res ^ (a[i] < t.a[i]);
return false;
}
bignum operator+(bignum t) const
{
if (op * t.op == -1)
{
t.op *= -1;
return *this - t;
}
bignum res;
res.op = op;
res.len = max(len, t.len);
int o = 0;
for (int i = 1; i <= res.len; i++)
{
res.a[i] = a[i] + t.a[i] + o;
o = res.a[i] / k;
res.a[i] %= k;
}
while (o)
{
res.a[++res.len] = o % k;
o /= k;
}
return res;
}
bignum operator-(bignum t) const
{
if (op * t.op == -1)
{
t.op *= -1;
return *this + t;
}
bignum res;
if ((op == 1 && *this < t) || (op == -1 && t < *this))
{
res = t - *this;
res.op *= -1;
return res;
}
res.op = op;
res.len = len;
for (int i = 1; i <= len; i++)
res.a[i] = a[i] - t.a[i];
for (int i = 1; i <= res.len; i++)
if (res.a[i] < 0)
res.a[i] += k, res.a[i + 1]--;
while (res.len > 0 && res.a[res.len] == 0)
res.len--;
if (res.len == 0)
res.op = 1;
return res;
}
bignum operator*(int t) const
{
bignum res;
if (t == 0)
{
res.len = 0;
return res;
}
res.op = op * t / abs(t);
t = abs(t);
res.len = len;
for (int i = 1; i <= len; i++)
res.a[i] = a[i] * t;
int o = 0;
for (int i = 1; i <= res.len; i++)
{
res.a[i] += o;
o = res.a[i] / k;
res.a[i] %= k;
}
while (o)
{
res.a[++res.len] = o % k;
o /= k;
}
if (res.len == 0)
res.op = 1;
return res;
}
bignum operator/(int t) const
{
bignum res;
res.op = op * t / abs(t);
t = abs(t);
res.len = len;
int o = 0;
for (int i = len; i >= 1; i--)
{
o = o * k + a[i];
res.a[i] = o / t;
o %= t;
}
while (res.len > 0 && res.a[res.len] == 0)
res.len--;
return res;
}
};

浙公网安备 33010602011771号