模板库

策略

第一步

Check List:(B-ALIVE)

  • ⭐️Border:调不出来一定记得检查所有边界!!!
  • Array:数组大小别开错(翻 \(k\) 倍、双向边开两倍等)
  • Longlong long (1ll << x)、mmul1ll
  • Init:多测(滚动)数组要清空、忌用memset,单测也要记得初始化数组
  • Value:树状数组等数据结构的范围(权值上的)
  • Exceed:小心MLETLE
  • 'Define':尝试还原宏定义

第二步

Prepare:

  • Theme
  • Auto-save
  • Clap
  • Snippets
    • init
    • edge
    • mod
    • read/write
    • segtree
    • disjointset
    • dinic

第三步(10min)

读题,读数据范围,模拟样例。

第四步(50min)

从简单到难,想所有题。

  1. 观察性质
  2. 大胆猜测
  3. 简化性质
  4. 构造双射

想正解;如果没有头绪就一定要想暴力。

验证解法正确性、细节、时间复杂度

记录做法、分数。

第五步(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;
    }
};
posted @ 2024-09-30 22:20  Aquizahv  阅读(65)  评论(0)    收藏  举报