栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

VS Code代码提示( AcWing算法模板,C++实现)

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

VS Code代码提示( AcWing算法模板,C++实现)

算法模板提取于AcWing上的代码提示

作者:yxc
链接:https://www.acwing.com/file_system/file/content/whole/index/content/2145234/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

已收录的模板及对应的唤醒词列表

vector add	add - 高精度加法	
vector sub	sub - 高精度减法	
vector mul	mul - 高精度乘低精度	
vector div	div - 高精度除以低精度	
int lo	int lowbit - 找末尾1	
void man	void manacher - 马拉车算法	算法进阶课 ———— 第七章 基础算法
void mer	void merge_sort - 归并排序	
void bu	void build - AC自动机	算法提高课 ———— 第四章 高级数据结构
int lo	int lowbit - 树状数组	算法提高课 ———— 第四章 高级数据结构
bool dfs	bool dfs - DLX重复覆盖	算法进阶课 ———— 第二章 数据结构
bool dfs	bool dfs - DLX精确覆盖	算法进阶课 ———— 第二章 数据结构
int find	int find - 并查集	
int mer	int merge - 左偏树	算法进阶课 ———— 第二章 数据结构
void spl	void splay - 动态树	算法进阶课 ———— 第二章 数据结构
void bu	void build - 线段树	算法提高课 ———— 第四章 高级数据结构
void spl	void splay - splay	算法进阶课 ———— 第二章 数据结构
ULL get	ULL get - 字符串哈希	
void get_sa	void get_sa - 后缀数组	算法进阶课 ———— 第二章 数据结构
void ext	void extend - 后缀自动机	算法进阶课 ———— 第二章 数据结构
void ins	void insert - Trie 插入	
void ad	void add - 加边,不带权	
void ad	void add - 加边,带权	
void ad	void add - 加边,最大流	算法进阶课 ———— 第一章 图论
void ad	void add - 加边,费用流	算法进阶课 ———— 第一章 图论
void cost	void cost_flow - 费用流	算法进阶课 ———— 第一章 图论
int cost	int cost_flow - 费用流	算法进阶课 ———— 第一章 图论
int dij	int dijkstra - 最短路	
void dij	void dijkstra - 最短路	
int din	int dinic - 最大流	算法进阶课 ———— 第一章 图论
void tar	tarjan - e-无向图双连通分量	算法提高课 ———— 第三章 图论
bool find	bool find - 匈牙利算法	
int lca	int lca - 倍增求LCA	算法提高课 ———— 第三章 图论
void tar	tarjan - 有向图强连通分量	算法提高课 ———— 第三章 图论
int spf	int spfa - 最短路	
void spf	void spfa - 最短路	
bool spf	bool spfa - 判负环	
void top	void topsort - 拓扑排序	
bool top	bool topsort - 拓扑排序	
void tar	tarjan - v-无向图双连通分量	算法提高课 ———— 第三章 图论
void andr	void andrew - 求凸包	算法进阶课 ———— 第四章 计算几何
void hal	half... - 求半平面交	算法进阶课 ———— 第四章 计算几何
int sig	int sign - 计算几何常用函数	算法进阶课 ———— 第四章 计算几何
double sim	double simpson - 辛普森积分	算法进阶课 ———— 第四章 计算几何
int bs	int bsgs - BSGS	算法进阶课 ———— 第五章 数学
int phi	int phi - 欧拉函数	
void get_eu	get_eulers - 线性筛欧拉函数	
void ff	void fft - FFT	算法进阶课 ———— 第五章 数学
int gau	gauss - 高斯消元(浮点值)	
void gau	gauss - 高斯消元(浮点值)	
int gau	gauss - 高斯消元(布尔值)	
void gau	gauss - 高斯消元(布尔值)	
int gc	int gcd - 欧几里得算法	
LL gc	LL gcd - 欧几里得算法	
int exgc	int exgcd - 扩展欧几里得算法	
int lu	int lucas - Lucas定理	
bool is_p	bool is_prime - 判定质数	
void get_p	void get_primes - 线性筛质数	
int qm	int qmi - 快速幂	
int qu	int quick_power - 快速幂	
void sim	simulate_anneal - 模拟退火	算法进阶课 ———— 第六章 搜索
int h	int h[N]...邻接表不带权	
int h	int h[N]...邻接表spfa	
int h	int h[N]...邻接表dijkstra	
int h	int h[N]...邻接表最大流	算法进阶课 ———— 第一章 图论
int h	int h[N]...邻接表费用流	算法进阶课 ———— 第一章 图论
int h	int h[N]...邻接表tarjan-scc	算法提高课 ———— 第三章 图论
int h	int h[N]...邻接表tarjan-e-dcc	算法提高课 ———— 第三章 图论
int h	int h[N]...邻接表tarjan-v-dcc	算法提高课 ———— 第三章 图论

VS Code配置,在设置中打开用户代码片段

在接下来的页面选择cpp.json

粘贴下面的代码,保存退出即可

{
  "add - 高精度加法": {
    "prefix": "vector add",
    "body": "vector add(vector &A, vector &B)  // C = A + B, A >= 0, B >= 0n{n    if (A.size() < B.size()) return add(B, A);nn    vector C;n    int t = 0;n    for (int i = 0; i < A.size(); i ++ )n    {n        t += A[i];n        if (i < B.size()) t += B[i];n        C.push_back(t % 10);n        t /= 10;n    }nn    if (t) C.push_back(t);n    return C;n}n",
    "description": "add - 高精度加法"
  },
  "sub - 高精度减法": {
    "prefix": "vector sub",
    "body": "vector sub(vector &A, vector &B)  // C = A - B, 满足A >= B, A >= 0, B >= 0n{n    vector C;n    for (int i = 0, t = 0; i < A.size(); i ++ )n    {n        t = A[i] - t;n        if (i < B.size()) t -= B[i];n        C.push_back((t + 10) % 10);n        if (t < 0) t = 1;n        else t = 0;n    }nn    while (C.size() > 1 && C.back() == 0) C.pop_back();n    return C;n}n",
    "description": "sub - 高精度减法"
  },
  "mul - 高精度乘低精度": {
    "prefix": "vector mul",
    "body": "vector mul(vector &A, int b)  // C = A * b, A >= 0, b >= 0n{n    vector C;nn    int t = 0;n    for (int i = 0; i < A.size() || t; i ++ )n    {n        if (i < A.size()) t += A[i] * b;n        C.push_back(t % 10);n        t /= 10;n    }nn    while (C.size() > 1 && C.back() == 0) C.pop_back();nn    return C;n}n",
    "description": "mul - 高精度乘低精度"
  },
  "div - 高精度除以低精度": {
    "prefix": "vector div",
    "body": "vector div(vector &A, int b, int &r)  // A / b = C ... r, A >= 0, b > 0n{n    vector C;n    r = 0;n    for (int i = A.size() - 1; i >= 0; i -- )n    {n        r = r * 10 + A[i];n        C.push_back(r / b);n        r %= b;n    }n    reverse(C.begin(), C.end());n    while (C.size() > 1 && C.back() == 0) C.pop_back();n    return C;n}n",
    "description": "div - 高精度除以低精度"
  },
  "int lowbit - 找末尾1": {
    "prefix": "int lowbit",
    "body": "int lowbit(int x)  // 返回末尾的1n{n    return x & -x;n}n",
    "description": "int lowbit - 找末尾1"
  },
  "void manacher - 马拉车算法": {
    "prefix": "void man",
    "body": "void init()  // a[]为原串,b[]为插入'#'后的新串n{n    int k = 0;n    b[k ++ ] = '$', b[k ++ ] = '#';n    for (int i = 0; i < n; i ++ ) b[k ++ ] = a[i], b[k ++ ] = '#';n    b[k ++ ] = '^';n    n = k;n}nnvoid manacher()  // 马拉车算法,b[]为插入'#'后的新串n{n    int mr = 0, mid;n    for (int i = 1; i < n; i ++ )n    {n        if (i < mr) p[i] = min(p[mid * 2 - i], mr - i);n        else p[i] = 1;n        while (b[i - p[i]] == b[i + p[i]]) p[i] ++ ;n        if (i + p[i] > mr)n        {n            mr = i + p[i];n            mid = i;n        }n    }n}n",
    "description": "void manacher - 马拉车算法"
  },
  "void merge_sort - 归并排序": {
    "prefix": "void merge_sort",
    "body": "void merge_sort(int q[], int l, int r)  // 归并排序n{n    if (l >= r) return;nn    int mid = l + r >> 1;n    merge_sort(q, l, mid);n    merge_sort(q, mid + 1, r);nn    int k = 0, i = l, j = mid + 1;n    while (i <= mid && j <= r)n        if (q[i] <= q[j]) tmp[k ++ ] = q[i ++ ];n        else tmp[k ++ ] = q[j ++ ];nn    while (i <= mid) tmp[k ++ ] = q[i ++ ];n    while (j <= r) tmp[k ++ ] = q[j ++ ];nn    for (i = l, j = 0; i <= r; i ++, j ++ ) q[i] = tmp[j];n}n",
    "description": "void merge_sort - 归并排序"
  },
  "void build - AC自动机": {
    "prefix": "void build",
    "body": "void insert(char str[])  // 将str插入Trie中n{n    int p = 0;n    for (int i = 0; str[i]; i ++ )n    {n        int u = str[i] - 'a';n        if (!tr[p][u]) tr[p][u] = ++ idx;n        p = tr[p][u];n    }n    cnt[p] ++ ;  // 记录单词出现次数n}nnvoid build()  // 创建AC自动机n{n    int hh = 0, tt = -1;n    for (int i = 0; i < 26; i ++ )n        if (tr[0][i])n            q[ ++ tt] = tr[0][i];n    while (hh <= tt)n    {n        int t = q[hh ++ ];n        for (int i = 0; i < 26; i ++ )n        {n            int p = tr[t][i];n            if (!p) tr[t][i] = tr[ne[t]][i];n            elsen            {n                ne[p] = tr[ne[t]][i];n                cnt[p] += cnt[ne[p]];n                q[ ++ tt] = p;n            }n        }n    }n}n",
    "description": "void build - AC自动机"
  },
  "int lowbit - 树状数组": {
    "prefix": "int lowbit",
    "body": "int lowbit(int x)n{n    return x & -x;n}nnvoid update(int x, int c)  // 位置x加cn{n    for (int i = x; i <= n; i += lowbit(i)) tr[i] += c;n}nnint query(int x)  // 返回前x个数的和n{n    int res = 0;n    for (int i = x; i; i -= lowbit(i)) res += tr[i];n    return res;n}n",
    "description": "int lowbit - 树状数组"
  },
  "bool dfs - DLX重复覆盖": {
    "prefix": "bool dfs",
    "body": "int l[N], r[N], u[N], d[N], col[N], row[N], s[N], idx;nint ans[N], top;  // 记录选择了哪些行nbool st[M];  // N为节点数,M为列数nnvoid init()  // 初始化十字链表n{n    for (int i = 0; i <= m; i ++ )n    {n        l[i] = i - 1, r[i] = i + 1;n        u[i] = d[i] = i;n        s[i] = 0, col[i] = i;n    }n    l[0] = m, r[m] = 0;n    idx = m + 1;n}nnvoid add(int& hh, int& tt, int x, int y)  // 在十字链表中插入节点n{n    row[idx] = x, col[idx] = y, s[y] ++ ;n    u[idx] = y, d[idx] = d[y], u[d[y]] = idx, d[y] = idx;n    r[hh] = l[tt] = idx, r[idx] = tt, l[idx] = hh;n    tt = idx ++ ;n}nnint h()  // IDA*的启发函数n{n    int res = 0;n    memset(st, 0, sizeof st);n    for (int i = r[0]; i; i = r[i])n    {n        if (st[col[i]]) continue;n        res ++ ;n        st[col[i]] = true;n        for (int j = d[i]; j != i; j = d[j])n            for (int k = r[j]; k != j; k = r[k])n                st[col[k]] = true;n    }n    return res;n}nnvoid remove(int p)n{n    for (int i = d[p]; i != p; i = d[i])n    {n        r[l[i]] = r[i];n        l[r[i]] = l[i];n    }n}nnvoid resume(int p)n{n    for (int i = u[p]; i != p; i = u[i])n    {n        r[l[i]] = i;n        l[r[i]] = i;n    }n}nnbool dfs(int k)n{n    if (k + h() > top) return false;n    if (!r[0])n    {n        top = k;n        return true;n    }n    int p = r[0];n    for (int i = r[0]; i; i = r[i])n        if (s[i] < s[p])n            p = i;n    for (int i = d[p]; i != p; i = d[i])n    {n        ans[k] = row[i];n        remove(i);n        for (int j = r[i]; j != i; j = r[j]) remove(j);n        if (dfs(k + 1)) return true;n        for (int j = l[i]; j != i; j = l[j]) resume(j);n        resume(i);n    }n    return false;n}n",
    "description": "bool dfs - DLX重复覆盖"
  },
  "bool dfs - DLX精确覆盖": {
    "prefix": "bool dfs",
    "body": "int l[N], r[N], u[N], d[N], col[N], row[N], s[N], idx;nint ans[N], top;  // 记录选择了哪些行nnvoid init()  // 初始化十字链表n{n    for (int i = 0; i <= m; i ++ )n    {n        l[i] = i - 1, r[i] = i + 1;n        u[i] = d[i] = i;n    }n    l[0] = m, r[m] = 0;n    idx = m + 1;n}nnvoid add(int& hh, int& tt, int x, int y)  // 在十字链表中添加节点n{n    row[idx] = x, col[idx] = y, s[y] ++ ;n    u[idx] = y, d[idx] = d[y], u[d[y]] = idx, d[y] = idx;n    r[hh] = l[tt] = idx, r[idx] = tt, l[idx] = hh;n    tt = idx ++ ;n}nnvoid remove(int p)n{n    r[l[p]] = r[p], l[r[p]] = l[p];n    for (int i = d[p]; i != p; i = d[i])n        for (int j = r[i]; j != i; j = r[j])n        {n            s[col[j]] -- ;n            d[u[j]] = d[j], u[d[j]] = u[j];n        }n}nnvoid resume(int p)n{n    for (int i = d[p]; i != p; i = d[i])n        for (int j = r[i]; j != i; j = r[j])n        {n            s[col[j]] ++ ;n            d[u[j]] = j, u[d[j]] = j;n        }n    r[l[p]] = p, l[r[p]] = p;n}nnbool dfs()n{n    if (!r[0]) return true;n    int p = r[0];n    for (int i = r[0]; i; i = r[i])n        if (s[i] < s[p])n            p = i;n    if (!s[p]) return false;n    remove(p);n    for (int i = d[p]; i != p; i = d[i])n    {n        ans[ ++ top] = row[i];n        for (int j = r[i]; j != i; j = r[j]) remove(col[j]);n        if (dfs()) return true;n        for (int j = r[i]; j != i; j = r[j]) resume(col[j]);n        top -- ;n    }n    resume(p);n    return false;n}n",
    "description": "bool dfs - DLX精确覆盖"
  },
  "int find - 并查集": {
    "prefix": "int find",
    "body": "int find(int x)  // 并查集n{n    if (p[x] != x) p[x] = find(p[x]);n    return p[x];n}n",
    "description": "int find - 并查集"
  },
  "int merge - 左偏树": {
    "prefix": "int merge",
    "body": "int v[N], dist[N], l[N], r[N], idx;nnbool cmp(int x, int y)  // 比较两个节点的权值大小n{n    if (v[x] != v[y]) return v[x] < v[y];n    return x < y;n}nnint merge(int x, int y)  // 合并两棵左偏树n{n    if (!x || !y) return x + y;n    if (cmp(y, x)) swap(x, y);n    r[x] = merge(r[x], y);n    if (dist[r[x]] > dist[l[x]]) swap(l[x], r[x]);n    dist[x] = dist[r[x]] + 1;n    return x;n}n",
    "description": "int merge - 左偏树"
  },
  "void splay - 动态树": {
    "prefix": "void splay",
    "body": "struct Noden{n    int s[2], p, v;n    int rev;n    // TODO: 定义需要维护的信息和懒标记n}tr[N];nint stk[N];  // 栈nnvoid pushrev(int x)n{n    swap(tr[x].s[0], tr[x].s[1]);n    tr[x].rev ^= 1;n}nnvoid pushup(int x)n{n    // TODO: 利用子节点信息来维护当前节点的信息n}nnvoid pushdown(int x)n{n    if (tr[x].rev)n    {n        pushrev(tr[x].s[0]), pushrev(tr[x].s[1]);n        tr[x].rev = 0;n    }n    // TODO: 将当前节点的懒标记下传n}nnbool isroot(int x)  // 判断x是否为原树的根节点n{n    return tr[tr[x].p].s[0] != x && tr[tr[x].p].s[1] != x;n}nnvoid rotate(int x)  // splay的旋转操作n{n    int y = tr[x].p, z = tr[y].p;n    int k = tr[y].s[1] == x;n    if (!isroot(y)) tr[z].s[tr[z].s[1] == y] = x;n    tr[x].p = z;n    tr[y].s[k] = tr[x].s[k ^ 1], tr[tr[x].s[k ^ 1]].p = y;n    tr[x].s[k ^ 1] = y, tr[y].p = x;n    pushup(y), pushup(x);n}nnvoid splay(int x)  // splay操作n{n    int top = 0, r = x;n    stk[ ++ top] = r;n    while (!isroot(r)) stk[ ++ top] = r = tr[r].p;n    while (top) pushdown(stk[top -- ]);n    while (!isroot(x))n    {n        int y = tr[x].p, z = tr[y].p;n        if (!isroot(y))n            if ((tr[y].s[1] == x) ^ (tr[z].s[1] == y)) rotate(x);n            else rotate(y);n        rotate(x);n    }n}nnvoid access(int x)  // 建立一条从根到x的路径,同时将x变成splay的根节点n{n    int z = x;n    for (int y = 0; x; y = x, x = tr[x].p)n    {n        splay(x);n        tr[x].s[1] = y, pushup(x);n    }n    splay(z);n}nnvoid makeroot(int x)  // 将x变成原树的根节点n{n    access(x);n    pushrev(x);n}nnint findroot(int x)  // 找到x所在原树的根节点, 再将原树的根节点旋转到splay的根节点n{n    access(x);n    while (tr[x].s[0]) pushdown(x), x = tr[x].s[0];n    splay(x);n    return x;n}nnvoid split(int x, int y)  // 给x和y之间的路径建立一个splay,其根节点是yn{n    makeroot(x);n    access(y);n}nnvoid link(int x, int y)  // 如果x和y不连通,则加入一条x和y之间的边n{n    makeroot(x);n    if (findroot(y) != x) tr[x].p = y;n}nnvoid cut(int x, int y)  // 如果x和y之间存在边,则删除该边n{n    makeroot(x);n    if (findroot(y) == x && tr[y].p == x && !tr[y].s[0])n    {n        tr[x].s[1] = tr[y].p = 0;n        pushup(x);n    }n}n",
    "description": "void splay - 动态树"
  },
  "void build - 线段树": {
    "prefix": "void build",
    "body": "struct Noden{n    int l, r;n    // TODO: 需要维护的信息和懒标记n}tr[N * 4];nnvoid pushup(int u)n{n    // TODO: 利用左右儿子信息维护当前节点的信息n}nnvoid pushdown(int u)n{n    // TODO: 将懒标记下传n}nnvoid build(int u, int l, int r)n{n    if (l == r) tr[u] = {l, r};n    elsen    {n        tr[u] = {l, r};n        int mid = l + r >> 1;n        build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);n        pushup(u);n    }n}nnvoid update(int u, int l, int r, int d)n{n    if (tr[u].l >= l && tr[u].r <= r)n    {n        // TODO: 修改区间n    }n    elsen    {n        pushdown(u);n        int mid = tr[u].l + tr[u].r >> 1;n        if (l <= mid) update(u << 1, l, r, d);n        if (r > mid) update(u << 1 | 1, l, r, d);n        pushup(u);n    }n}nnint query(int u, int l, int r)n{n    if (tr[u].l >= l && tr[u].r <= r)n    {n        return ;  // TODO 需要补充返回值n    }n    elsen    {n        pushdown(u);n        int mid = tr[u].l + tr[u].r >> 1;n        int res = 0;n        if (l <= mid ) res = query(u << 1, l, r);n        if (r > mid) res += query(u << 1 | 1, l, r);n        return res;n    }n}n",
    "description": "void build - 线段树"
  },
  "void splay - splay": {
    "prefix": "void splay",
    "body": "struct Noden{n    int s[2], p, v;n    int size;n    n    void init(int _v, int _p)n    {n        v = _v, p = _p;n        size = 1;n    }n}tr[N];nint root, idx;nnvoid pushup(int x)n{n    // TODO: 利用子节点信息维护当前节点信息n}nnvoid pushdown(int x)n{n    // TODO: 将懒标记下传n}nnvoid rotate(int x)  // 旋转n{n    int y = tr[x].p, z = tr[y].p;n    int k = tr[y].s[1] == x;n    tr[z].s[tr[z].s[1] == y] = x, tr[x].p = z;n    tr[y].s[k] = tr[x].s[k ^ 1], tr[tr[x].s[k ^ 1]].p = y;n    tr[x].s[k ^ 1] = y, tr[y].p = x;n    pushup(y), pushup(x);n}nnvoid splay(int x, int k)  // splay操作n{n    while (tr[x].p != k)n    {n        int y = tr[x].p, z = tr[y].p;n        if (z != k)n            if ((tr[y].s[1] == x) ^ (tr[z].s[1] == y)) rotate(x);n            else rotate(y);n        rotate(x);n    }n    if (!k) root = x;n}n",
    "description": "void splay - splay"
  },
  "ULL get - 字符串哈希": {
    "prefix": "ULL get",
    "body": "ULL get(int l, int r)  // 计算子串 str[l ~ r] 的哈希值n{n    return h[r] - h[l - 1] * p[r - l + 1];n}n",
    "description": "ULL get - 字符串哈希"
  },
  "void get_sa - 后缀数组": {
    "prefix": "void get_sa",
    "body": "char s[N];  // 存储原字符串nint sa[N], rk[N], x[N], y[N], height[N], c[N];nnvoid get_sa()  // 创建后缀数组n{n    for (int i = 1; i <= n; i ++ ) c[x[i] = s[i]] ++ ;n    for (int i = 2; i <= m; i ++ ) c[i] += c[i - 1];n    for (int i = n; i; i -- ) sa[c[x[i]] -- ] = i;n    for (int k = 1; k <= n; k <<= 1)n    {n        int num = 0;n        for (int i = n - k + 1; i <= n; i ++ ) y[ ++ num] = i;n        for (int i = 1; i <= n; i ++ )n            if (sa[i] > k)n                y[ ++ num] = sa[i] - k;n        for (int i = 1; i <= m; i ++ ) c[i] = 0;n        for (int i = 1; i <= n; i ++ ) c[x[i]] ++ ;n        for (int i = 2; i <= m; i ++ ) c[i] += c[i - 1];n        for (int i = n; i; i -- ) sa[c[x[y[i]]] -- ] = y[i], y[i] = 0;n        swap(x, y);n        x[sa[1]] = 1, num = 1;n        for (int i = 2; i <= n; i ++ )n            x[sa[i]] = (y[sa[i]] == y[sa[i - 1]] && y[sa[i] + k] == y[sa[i - 1] + k]) ? num : ++ num;n        if (num == n) break;n        m = num;n    }n}nnvoid get_height()  // 预处理height[]数组n{n    int k = 0;n    for (int i = 1; i <= n; i ++ ) rk[sa[i]] = i;n    for (int i = 1; i <= n; i ++ )n    {n        if (rk[i] == 1) continue;n        if (k) k -- ;n        int j = sa[rk[i] - 1];n        while (i + k <= n && j + k <= n && s[i + k] == s[j + k]) k ++ ;n        height[rk[i]] = k;n    }n}n",
    "description": "void get_sa - 后缀数组"
  },
  "void extend - 后缀自动机": {
    "prefix": "void extend",
    "body": "int tot = 1, last = 1;nstruct Noden{n    int len, fa;n    int ch[26];n}node[N];nnvoid extend(char c)n{n    int p = last, np = last = ++ tot;n    node[np].len = node[p].len + 1;n    for (; p && !node[p].ch[c]; p = node[p].fa) node[p].ch[c] = np;n    if (!p) node[np].fa = 1;n    elsen    {n        int q = node[p].ch[c];n        if (node[q].len == node[p].len + 1) node[np].fa = q;n        elsen        {n            int nq = ++ tot;n            node[nq] = node[q], node[nq].len = node[p].len + 1;n            node[q].fa = node[np].fa = nq;n            for (; p && node[p].ch[c] == q; p = node[p].fa) node[p].ch[c] = nq;n        }n    }n}n",
    "description": "void extend - 后缀自动机"
  },
  "void insert - Trie 插入": {
    "prefix": "void insert",
    "body": "int son[N][26], cnt[N], idx;nnvoid insert(char *str)  // 插入字符串n{n    int p = 0;n    for (int i = 0; str[i]; i ++ )n    {n        int u = str[i] - 'a';n        if (!son[p][u]) son[p][u] = ++ idx;n        p = son[p][u];n    }n    cnt[p] ++ ;n}nnint query(char *str)  // 查询字符串出现次数n{n    int p = 0;n    for (int i = 0; str[i]; i ++ )n    {n        int u = str[i] - 'a';n        if (!son[p][u]) return 0;n        p = son[p][u];n    }n    return cnt[p];n}n",
    "description": "void insert - Trie 插入"
  },
  "void add - 加边,不带权": {
    "prefix": "void add",
    "body": "void add(int a, int b)  // 添加一条边a->bn{n    e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;n}n",
    "description": "void add - 加边,不带权"
  },
  "void add - 加边,带权": {
    "prefix": "void add",
    "body": "void add(int a, int b, int c)  // 添加一条边a->b,边权为cn{n    e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;n}n",
    "description": "void add - 加边,带权"
  },
  "void add - 加边,最大流": {
    "prefix": "void add",
    "body": "void add(int a, int b, int c)  // 添加一条边a->b,容量为c;同时添加一条反向边n{n    e[idx] = b, f[idx] = c, ne[idx] = h[a], h[a] = idx ++ ;n    e[idx] = a, f[idx] = 0, ne[idx] = h[b], h[b] = idx ++ ;n}n",
    "description": "void add - 加边,最大流"
  },
  "void add - 加边,费用流": {
    "prefix": "void add",
    "body": "void add(int a, int b, int c, int d)  // 添加一条边a->b,容量为c,费用为d;同时增加一条反向边n{n    e[idx] = b, f[idx] = c, w[idx] = d, ne[idx] = h[a], h[a] = idx ++ ;n    e[idx] = a, f[idx] = 0, w[idx] = -d, ne[idx] = h[b], h[b] = idx ++ ;n}n",
    "description": "void add - 加边,费用流"
  },
  "void cost_flow - 费用流": {
    "prefix": "void cost_flow",
    "body": "bool spfa()  // 找距离最短的增广路n{n    int hh = 0, tt = 1;n    memset(d, 0x3f, sizeof d);n    q[0] = S, d[S] = 0, incf[S] = INF;n    while (hh != tt)n    {n        int t = q[hh ++ ];n        if (hh == N) hh = 0;n        st[t] = false;n        for (int i = h[t]; ~i; i = ne[i])n        {n            int ver = e[i];n            if (f[i] && d[ver] > d[t] + w[i])n            {n                d[ver] = d[t] + w[i];n                pre[ver] = i;n                incf[ver] = min(f[i], incf[t]);n                if (!st[ver])n                {n                    q[tt ++ ] = ver;n                    if (tt == N) tt = 0;n                    st[ver] = true;n                }n            }n        }n    }n    return d[T] != INF;n}nnvoid cost_flow(int& flow, int& cost)n{n    flow = cost = 0;  // flow存储流量,cost存储费用n    while (spfa())n    {n        int t = incf[T];n        flow += t, cost += t * d[T];n        for (int i = T; i != S; i = e[pre[i] ^ 1])n        {n            f[pre[i]] -= t;n            f[pre[i] ^ 1] += t;n        }n    }n}n",
    "description": "void cost_flow - 费用流"
  },
  "int cost_flow - 费用流": {
    "prefix": "int cost_flow",
    "body": "bool spfa()  // 找距离最短的增广路n{n    int hh = 0, tt = 1;n    memset(d, 0x3f, sizeof d);n    q[0] = S, d[S] = 0, incf[S] = INF;n    while (hh != tt)n    {n        int t = q[hh ++ ];n        if (hh == N) hh = 0;n        st[t] = false;n        for (int i = h[t]; ~i; i = ne[i])n        {n            int ver = e[i];n            if (f[i] && d[ver] > d[t] + w[i])n            {n                d[ver] = d[t] + w[i];n                pre[ver] = i;n                incf[ver] = min(f[i], incf[t]);n                if (!st[ver])n                {n                    q[tt ++ ] = ver;n                    if (tt == N) tt = 0;n                    st[ver] = true;n                }n            }n        }n    }n    return d[T] != INF;n}nnint cost_flow()n{n    int cost = 0;  // 存储费用n    while (spfa())n    {n        int t = incf[T];n        cost += t * d[T];n        for (int i = T; i != S; i = e[pre[i] ^ 1])n        {n            f[pre[i]] -= t;n            f[pre[i] ^ 1] += t;n        }n    }n    return cost;n}n",
    "description": "int cost_flow - 费用流"
  },
  "int dijkstra - 最短路": {
    "prefix": "int dijkstra",
    "body": "int dijkstra()  // 求1号点到n号点的最短路距离,如果从1号点无法走到n号点则返回-1n{n    memset(dist, 0x3f, sizeof dist);n    dist[1] = 0;n    priority_queue, greater> heap;n    heap.push({0, 1});nn    while (heap.size())n    {n        auto t = heap.top();n        heap.pop();nn        int ver = t.second, distance = t.first;nn        if (st[ver]) continue;n        st[ver] = true;nn        for (int i = h[ver]; i != -1; i = ne[i])n        {n            int j = e[i];n            if (dist[j] > dist[ver] + w[i])n            {n                dist[j] = dist[ver] + w[i];n                heap.push({dist[j], j});n            }n        }n    }nn    if (dist[n] == 0x3f3f3f3f) return -1;n    return dist[n];n}n",
    "description": "int dijkstra - 最短路"
  },
  "void dijkstra - 最短路": {
    "prefix": "void dijkstra",
    "body": "void dijkstra()  // 求1号点到n号点的最短路距离n{n    memset(dist, 0x3f, sizeof dist);n    dist[1] = 0;n    priority_queue, greater> heap;n    heap.push({0, 1});nn    while (heap.size())n    {n        auto t = heap.top();n        heap.pop();nn        int ver = t.second, distance = t.first;nn        if (st[ver]) continue;n        st[ver] = true;nn        for (int i = h[ver]; i != -1; i = ne[i])n        {n            int j = e[i];n            if (dist[j] > dist[ver] + w[i])n            {n                dist[j] = dist[ver] + w[i];n                heap.push({dist[j], j});n            }n        }n    }n}n",
    "description": "void dijkstra - 最短路"
  },
  "int dinic - 最大流": {
    "prefix": "int dinic",
    "body": "bool bfs()  // 创建分层图n{n    int hh = 0, tt = 0;n    memset(d, -1, sizeof d);n    q[0] = S, d[S] = 0, cur[S] = h[S];n    while (hh <= tt)n    {n        int t = q[hh ++ ];n        for (int i = h[t]; ~i; i = ne[i])n        {n            int ver = e[i];n            if (d[ver] == -1 && f[i])n            {n                d[ver] = d[t] + 1;n                cur[ver] = h[ver];n                if (ver == T) return true;n                q[ ++ tt] = ver;n            }n        }n    }n    return false;  // 没有增广路n}nnint find(int u, int limit)  // 在残留网络中增广n{n    if (u == T) return limit;n    int flow = 0;n    for (int i = cur[u]; ~i && flow < limit; i = ne[i])n    {n        cur[u] = i;  // 当前弧优化n        int ver = e[i];n        if (d[ver] == d[u] + 1 && f[i])n        {n            int t = find(ver, min(f[i], limit - flow));n            if (!t) d[ver] = -1;n            f[i] -= t, f[i ^ 1] += t, flow += t;n        }n    }n    return flow;n}nnint dinic()n{n    int r = 0, flow;n    while (bfs()) while (flow = find(S, INF)) r += flow;n    return r;n}n",
    "description": "int dinic - 最大流"
  },
  "tarjan - e-无向图双连通分量": {
    "prefix": "void tar",
    "body": "void tarjan(int u, int from)n{n    dfn[u] = low[u] = ++ timestamp;n    stk[ ++ top] = u;n    n    for (int i = h[u]; ~i; i = ne[i])n    {n        int j = e[i];n        if (!dfn[j])n        {n            tarjan(j, i);n            low[u] = min(low[u], low[j]);n            if (dfn[u] < low[j])n                is_bridge[i] = is_bridge[i ^ 1] = true;n        }n        else if (i != (from ^ 1))n            low[u] = min(low[u], dfn[j]);n    }n    n    if (dfn[u] == low[u])n    {n        ++ dcc_cnt;n        int y;n        do {n            y = stk[top -- ];n            id[y] = dcc_cnt;n        } while (y != u);n    }n}n",
    "description": "tarjan - e-无向图双连通分量"
  },
  "bool find - 匈牙利算法": {
    "prefix": "bool find",
    "body": "bool find(int x)n{n    for (int i = h[x]; i != -1; i = ne[i])n    {n        int j = e[i];n        if (!st[j])n        {n            st[j] = true;n            if (match[j] == 0 || find(match[j]))n            {n                match[j] = x;n                return true;n            }n        }n    }n    n    return false;n}n",
    "description": "bool find - 匈牙利算法"
  },
  "int lca - 倍增求LCA": {
    "prefix": "int lca",
    "body": "void bfs(int root)  // 预处理倍增数组n{n    memset(depth, 0x3f, sizeof depth);n    depth[0] = 0, depth[root] = 1;  // depth存储节点所在层数n    int hh = 0, tt = 0;n    q[0] = root;n    while (hh <= tt)n    {n        int t = q[hh ++ ];n        for (int i = h[t]; ~i; i = ne[i])n        {n            int j = e[i];n            if (depth[j] > depth[t] + 1)n            {n                depth[j] = depth[t] + 1;n                q[ ++ tt] = j;n                fa[j][0] = t;  // j的第二次幂个父节点n                for (int k = 1; k <= 15; k ++ )n                    fa[j][k] = fa[fa[j][k - 1]][k - 1];n            }n        }n    }n}nnint lca(int a, int b)  // 返回a和b的最近公共祖先n{n    if (depth[a] < depth[b]) swap(a, b);n    for (int k = 15; k >= 0; k -- )n        if (depth[fa[a][k]] >= depth[b])n            a = fa[a][k];n    if (a == b) return a;n    for (int k = 15; k >= 0; k -- )n        if (fa[a][k] != fa[b][k])n        {n            a = fa[a][k];n            b = fa[b][k];n        }n    return fa[a][0];n}n",
    "description": "int lca - 倍增求LCA"
  },
  "tarjan - 有向图强连通分量": {
    "prefix": "void tarjan",
    "body": "void tarjan(int u)n{n    dfn[u] = low[u] = ++ timestamp;n    stk[ ++ top] = u, in_stk[u] = true;n    n    for (int i = h[u]; ~i; i = ne[i])n    {n        int j = e[i];n        if (!dfn[j])n        {n            tarjan(j);n            low[u] = min(low[u], low[j]);n        }n        else if (in_stk[j])n            low[u] = min(low[u], dfn[j]);n    }n    n    if (dfn[u] == low[u])n    {n        ++ scc_cnt;n        int y;n        do {n            y = stk[top -- ];n            in_stk[y] = false;n            id[y] = scc_cnt;n        } while (y != u);n    }n}n",
    "description": "tarjan - 有向图强连通分量"
  },
  "int spfa - 最短路": {
    "prefix": "int spfa",
    "body": "int spfa()  // 求1号点到n号点的最短路距离,如果从1号点无法走到n号点则返回-1n{n    int hh = 0, tt = 0;n    memset(dist, 0x3f, sizeof dist);n    dist[1] = 0;n    q[tt ++ ] = 1;n    st[1] = true;nn    while (hh != tt)n    {n        int t = q[hh ++ ];n        if (hh == N) hh = 0;n        st[t] = false;n        n        for (int i = h[t]; i != -1; i = ne[i])n        {n            int j = e[i];n            if (dist[j] > dist[t] + w[i])n            {n                dist[j] = dist[t] + w[i];n                if (!st[j])     // 如果队列中已存在j,则不需要将j重复插入n                {n                    q[tt ++ ] = j;n                    if (tt == N) tt = 0;n                    st[j] = true;n                }n            }n        }n    }nn    if (dist[n] == 0x3f3f3f3f) return -1;n    return dist[n];n}n",
    "description": "int spfa - 最短路"
  },
  "void spfa - 最短路": {
    "prefix": "void spfa",
    "body": "void spfa()  // 求1号点到n号点的最短路距离n{n    int hh = 0, tt = 0;n    memset(dist, 0x3f, sizeof dist);n    dist[1] = 0;n    q[tt ++ ] = 1;n    st[1] = true;nn    while (hh != tt)n    {n        int t = q[hh ++ ];n        if (hh == N) hh = 0;n        st[t] = false;n        n        for (int i = h[t]; i != -1; i = ne[i])n        {n            int j = e[i];n            if (dist[j] > dist[t] + w[i])n            {n                dist[j] = dist[t] + w[i];n                if (!st[j])     // 如果队列中已存在j,则不需要将j重复插入n                {n                    q[tt ++ ] = j;n                    if (tt == N) tt = 0;n                    st[j] = true;n                }n            }n        }n    }n}n",
    "description": "void spfa - 最短路"
  },
  "bool spfa - 判负环": {
    "prefix": "bool spfa",
    "body": "bool spfa()  // 如果存在负环,则返回true,否则返回false。n{n    // 不需要初始化dist数组n    // 原理:如果某条最短路径上有n个点(除了自己),那么加上自己之后一共有n+1个点,n    // 由抽屉原理一定有两个点相同,所以存在环。nn    int hh = 0, tt = 0;n    n    for (int i = 1; i <= n; i ++ ) q[tt ++ ] = i, st[i] = true;n    n    while (hh != tt)n    {n        int t = q[hh ++ ];n        if (hh == N) hh = 0;n        st[t] = false;n        n        for (int i =  h[t]; ~i; i = ne[i])n        {n            int j = e[i];n            if (dist[j] > dist[t] + w[i])n            {n                dist[j] = dist[t]  + w[i];n                cnt[j] = cnt[t] + 1;n                if (cnt[j] >= n) return true;n                if (!st[j])n                {n                    st[j] = true;n                    q[tt ++ ] = j;n                    if (tt == N) tt = 0;n                }n            }n        }n    }n    n    return false;n}n",
    "description": "bool spfa - 判负环"
  },
  "void topsort - 拓扑排序": {
    "prefix": "void topsort",
    "body": "void topsort()n{n    int hh = 0, tt = -1;nn    // d[i] 存储点i的入度n    for (int i = 1; i <= n; i ++ )n        if (!d[i])n            q[ ++ tt] = i;nn    while (hh <= tt)n    {n        int t = q[hh ++ ];nn        for (int i = h[t]; i != -1; i = ne[i])n        {n            int j = e[i];n            if (-- d[j] == 0)n                q[ ++ tt] = j;n        }n    }n}n",
    "description": "void topsort - 拓扑排序"
  },
  "bool topsort - 拓扑排序": {
    "prefix": "bool topsort",
    "body": "bool topsort()n{n    int hh = 0, tt = -1;nn    // d[i] 存储点i的入度n    for (int i = 1; i <= n; i ++ )n        if (!d[i])n            q[ ++ tt] = i;nn    while (hh <= tt)n    {n        int t = q[hh ++ ];nn        for (int i = h[t]; i != -1; i = ne[i])n        {n            int j = e[i];n            if (-- d[j] == 0)n                q[ ++ tt] = j;n        }n    }nn    // 如果所有点都入队了,说明存在拓扑序列;否则不存在拓扑序列。n    return tt == n - 1;n}n",
    "description": "bool topsort - 拓扑排序"
  },
  "tarjan - v-无向图双连通分量": {
    "prefix": "void tarjan",
    "body": "void tarjan(int u)n{n    dfn[u] = low[u] = ++ timestamp;n    stk[ ++ top] = u;n    n    if (u == root && h[u] == -1)n    {n        dcc_cnt ++ ;n        dcc[dcc_cnt].push_back(u);n        return;n    }n    n    int cnt = 0;n    for (int i = h[u]; ~i; i = ne[i])n    {n        int j = e[i];n        if (!dfn[j])n        {n            tarjan(j);n            low[u] = min(low[u], low[j]);n            if (dfn[u] <= low[j])n            {n                cnt ++ ;n                if (u != root || cnt > 1) cut[u] = true;n                ++ dcc_cnt;n                int y;n                do {n                    y = stk[top -- ];n                    dcc[dcc_cnt].push_back(y);n                } while (y != j);n                dcc[dcc_cnt].push_back(u);n            }n        }n        else low[u] = min(low[u], dfn[j]);n    }n}n",
    "description": "tarjan - v-无向图双连通分量"
  },
  "int bsgs - BSGS": {
    "prefix": "int bsgs",
    "body": "int bsgs(int a, int b, int p)  // a ^ x ≡ b (mod p) 的最小非负整数解n{n    if (b == 1) return 0;n    int k = sqrt(p) + 1;n    unordered_map hash;n    for (int i = 0, j = b; i < k; i ++ )n    {n        hash[j] = i;n        j = (LL)j * a % p;n    }n    int ak = 1;n    for (int i = 0; i < k; i ++ ) ak = (LL)ak * a % p;n    for (int i = 1, j = ak; i <= k; i ++ )n    {n        if (hash.count(j) && (LL)i * k >= hash[j])n            return (LL)i * k - hash[j];n        j = (LL)j * ak % p;n    }n    return -1;n}n",
    "description": "int bsgs - BSGS"
  },
  "void andrew - 求凸包": {
    "prefix": "void andrew",
    "body": "int stk[N], top;nPDD q[N];nbool used[N];nnPDD operator- (PDD a, PDD b)  // 向量减法n{n    return {a.x - b.x, a.y - b.y};n}nndouble operator* (PDD a, PDD b)  // 叉积、外积n{n    return a.x * b.y - a.y * b.x;n}nndouble operator& (PDD a, PDD b)  // 内积、点积n{n    return a.x * b.x + a.y * b.y;n}nndouble area(PDD a, PDD b, PDD c)  // 以a, b, c为顶点的有向三角形面积n{n    return (b - a) * (c - a);n}nndouble get_len(PDD a)  // 求向量长度n{n    return sqrt(a & a);n}nndouble get_dist(PDD a, PDD b)  // 求两个点之间的距离n{n    return get_len(b - a);n}nnvoid andrew()  // Andrew算法, 凸包节点编号逆时针存于stk中,下标从0开始n{n    sort(q, q + n);n    for (int i = 0; i < n; i ++ )n    {n        while (top >= 2 && area(q[stk[top - 2]], q[stk[top - 1]], q[i]) <= 0)n        {n            if (area(q[stk[top - 2]], q[stk[top - 1]], q[i]) < 0)n                used[stk[ -- top]] = false;n            elsen                top -- ;n        }n        stk[top ++ ] = i;n        used[i] = true;n    }n    used[0] = false;n    for (int i = n - 1; i >= 0; i -- )n    {n        if (used[i]) continue;n        while (top >= 2 && area(q[stk[top - 2]], q[stk[top - 1]], q[i]) <= 0)n            top -- ;n        stk[top ++ ] = i;n    }n    top -- ;  // 起点重复添加了一次,将其去掉n}n",
    "description": "void andrew - 求凸包"
  },
  "half... - 求半平面交": {
    "prefix": "void half",
    "body": "void struct Line  // 直线n{n    PDD st, ed;  // 直线上的两个点n}line[N];nint q[N];  // 双端队列nnint sign(double x)  // 符号函数n{n    if (fabs(x) < eps) return 0;  // x为0,则返回0n    if (x < 0) return -1;  // x为负数,则返回-1n    return 1;  // x为正数,则返回1n}nnint dcmp(double x, double y)  // 比较两数大小n{n    if (fabs(x - y) < eps) return 0;  // x == y, 返回0n    if (x < y) return -1;  // x < y, 返回-1n    return 1;  // x > y, 返回1n}nnPDD operator+ (PDD a, PDD b)  // 向量加法n{n    return {a.x + b.x, a.y + b.y};n}nnPDD operator-(PDD a, PDD b)  // 向量减法n{n    return {a.x - b.x, a.y - b.y};n}nndouble operator* (PDD a, PDD b)  // 外积、叉积n{n    return a.x * b.y - a.y * b.x;n}nnPDD operator* (PDD a, double t)  // 向量数乘n{n    return {a.x * t, a.y * t};n}nndouble area(PDD a, PDD b, PDD c)  // 以a, b, c为顶点的有向三角形面积n{n    return (b - a) * (c - a);n}nnPDD get_line_intersection(PDD p, PDD v, PDD q, PDD w)  // 求两直线交点:p + vt, q + wtn{n    auto u = p - q;n    auto t = w * u / (v * w);n    return p + v * t;n}nnPDD get_line_intersection(Line a, Line b)  // 求两直线交点n{n    return get_line_intersection(a.st, a.ed - a.st, b.st, b.ed - b.st);n}nnbool on_right(Line& a, Line& b, Line& c) // bc的交点是否在a的右侧n{n    auto o = get_line_intersection(b, c);n    return sign(area(a.st, a.ed, o)) <= 0;n}nndouble get_angle(const Line& a)  // 求直线的极角大小n{n    return atan2(a.ed.y - a.st.y, a.ed.x - a.st.x);n}nnbool cmp(const Line& a, const Line& b)  // 将所有直线按极角排序n{n    double A = get_angle(a), B = get_angle(b);n    if (!dcmp(A, B)) return area(a.st, a.ed, b.ed) < 0;n    return A < B;n}nnvoid half_plane_intersection()  // 半平面交,交集的边逆时针顺序存于q[]中n{n    sort(line, line + cnt, cmp);n    int hh = 0, tt = -1;n    for (int i = 0; i < cnt; i ++ )n    {n        if (i && !dcmp(get_angle(line[i]), get_angle(line[i - 1]))) continue;n        while (hh + 1 <= tt && on_right(line[i], line[q[tt - 1]], line[q[tt]])) tt -- ;n        while (hh + 1 <= tt && on_right(line[i], line[q[hh]], line[q[hh + 1]])) hh ++ ;n        q[ ++ tt] = i;n    }n    while (hh + 1 <= tt && on_right(line[q[hh]], line[q[tt - 1]], line[q[tt]])) tt -- ;n    while (hh + 1 <= tt && on_right(line[q[tt]], line[q[hh]], line[q[hh + 1]])) hh ++ ;n    n    q[ ++ tt] = q[hh];n    // 交集的边逆时针顺序存于q[]中n    n    // TODO: 求出半平面交后,根据题目要求求答案n}n",
    "description": "half... - 求半平面交"
  },
  "int sign - 计算几何常用函数": {
    "prefix": "int sign",
    "body": "int sign(double x)  // 符号函数n{n    if (fabs(x) < eps) return 0;  // x为0,则返回0n    if (x < 0) return -1;  // x为负数,则返回-1n    return 1;  // x为正数,则返回1n}nnint dcmp(double x, double y)  // 比较两数大小n{n    if (fabs(x - y) < eps) return 0;  // x == y, 返回0n    if (x < y) return -1;  // x < y, 返回-1n    return 1;  // x > y, 返回1n}nnPDD operator+ (PDD a, PDD b)  // 向量加法n{n    return {a.x + b.x, a.y + b.y};n}nnPDD operator- (PDD a, PDD b)  //  向量减法n{n    return {a.x - b.x, a.y - b.y};n}nnPDD operator* (PDD a, double t)  // 向量数乘n{n    return {a.x * t, a.y * t};n}nnPDD operator/ (PDD a, double t)  // 向量除以常数n{n    return {a.x / t, a.y / t};n}nndouble operator* (PDD a, PDD b)  // 外积、叉积n{n    return a.x * b.y - a.y * b.x;n}nndouble operator& (PDD a, PDD b)  // 内积、点积n{n    return a.x * b.x + a.y * b.y;n}nndouble area(PDD a, PDD b, PDD c)  // 以a, b, c为顶点的有向三角形面积n{n    return (b - a) * (c - a);n}nndouble get_len(PDD a)  // 求向量长度n{n    return sqrt(a & a);n}nndouble get_dist(PDD a, PDD b)  // 求两个点之间的距离n{n    return get_len(b - a);n}nndouble project(PDD a, PDD b, PDD c)  // 求向量ac在向量ab上的投影n{n    return ((c - a) & (b - a)) / get_len(b - a);n}nnPDD rotate(PDD a, double b)  // 向量a逆时针旋转角度bn{n    return {a.x * cos(b) + a.y * sin(b), -a.x * sin(b) + a.y * cos(b)};n}nnPDD norm(PDD a)  // 矩阵标准化(将长度变成1)n{n    return a / get_len(a);n}nnbool on_segment(PDD p, PDD a, PDD b)  // 点p是否在线段ab上(包含端点a、b)n{n    return !sign((p - a) * (p - b)) && sign((p - a) & (p - b)) <= 0;n}nnPDD get_line_intersection(PDD p, PDD v, PDD q, PDD w)  // 求两直线交点:p + vt, q + wtn{n    auto u = p - q;n    auto t = w * u / (v * w);n    return p + v * t;n}n",
    "description": "int sign - 计算几何常用函数"
  },
  "double simpson - 辛普森积分": {
    "prefix": "double simpson",
    "body": "double f(double x)n{n    // TODO: 实现所求的函数n}nndouble simpson(double l, double r)  // 辛普森积分公式n{n    auto mid = (l + r) / 2;n    return (r - l) * (f(l) + 4 * f(mid) + f(r)) / 6;n}nndouble asr(double l, double r, double s)  // 自适应n{n    auto mid = (l + r) / 2;n    auto left = simpson(l, mid), right = simpson(mid, r);n    if (fabs(left + right - s) < eps) return left + right;n    return asr(l, mid, left) + asr(mid, r, right);n}n",
    "description": "double simpson - 辛普森积分"
  },
  "int phi - 欧拉函数": {
    "prefix": "int phi",
    "body": "int phi(int x)  // 欧拉函数n{n    int res = x;n    for (int i = 2; i <= x / i; i ++ )n        if (x % i == 0)n        {n            res = res / i * (i - 1);n            while (x % i == 0) x /= i;n        }n    if (x > 1) res = res / x * (x - 1);nn    return res;n}n",
    "description": "int phi - 欧拉函数"
  },
  "get_eulers - 线性筛欧拉函数": {
    "prefix": "void get_eulers",
    "body": "void get_eulers(int n)  // 线性筛法求1~n的欧拉函数n{n    euler[1] = 1;n    for (int i = 2; i <= n; i ++ )n    {n        if (!st[i])n        {n            primes[cnt ++ ] = i;n            euler[i] = i - 1;n        }n        for (int j = 0; primes[j] <= n / i; j ++ )n        {n            int t = primes[j] * i;n            st[t] = true;n            if (i % primes[j] == 0)n            {n                euler[t] = euler[i] * primes[j];n                break;n            }n            euler[t] = euler[i] * (primes[j] - 1);n        }n    }n}n",
    "description": "get_eulers - 线性筛欧拉函数"
  },
  "void fft - FFT": {
    "prefix": "void fft",
    "body": "void struct Complexn{n    double x, y;n    Complex operator+ (const Complex& t) constn    {n        return {x + t.x, y + t.y};n    }n    Complex operator- (const Complex& t) constn    {n        return {x - t.x, y - t.y};n    }n    Complex operator* (const Complex& t) constn    {n        return {x * t.x - y * t.y, x * t.y + y * t.x};n    }n};nint rev[N], bit, tot;  // tot = 1 << bitnnvoid fft(Complex a[], int inv)n{n    for (int i = 0; i < tot; i ++ )n        rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (bit - 1));n    for (int i = 0; i < tot; i ++ )n        if (i < rev[i])n            swap(a[i], a[rev[i]]);n    for (int mid = 1; mid < tot; mid <<= 1)n    {n        auto w1 = Complex({cos(PI / mid), inv * sin(PI / mid)});n        for (int i = 0; i < tot; i += mid * 2)n        {n            auto wk = Complex({1, 0});n            for (int j = 0; j < mid; j ++, wk = wk * w1)n            {n                auto x = a[i + j], y = wk * a[i + j + mid];n                a[i + j] = x + y, a[i + j + mid] = x - y;n            }n        }n    }n}n",
    "description": "void fft - FFT"
  },
  "gauss - 高斯消元(浮点值)": {
    "prefix": "int gauss",
    "body": "int gauss()  // 高斯消元,答案存于a[i][n]中,0 <= i < nn{n    int c, r;n    for (c = 0, r = 0; c < n; c ++ )n    {n        int t = r;n        for (int i = r; i < n; i ++ )  // 找绝对值最大的行n            if (fabs(a[i][c]) > fabs(a[t][c]))n                t = i;n        n        if (fabs(a[t][c]) < eps) continue;n        n        for (int i = c; i <= n; i ++ ) swap(a[t][i], a[r][i]);  // 将绝对值最大的行换到最顶端n        for (int i = n; i >= c; i -- ) a[r][i] /= a[r][c];  // 将当前行的首位变成1n        for (int i = r + 1; i < n; i ++ )  // 用当前行将下面所有的列消成0n            if (fabs(a[i][c]) > eps)n                for (int j = n; j >= c; j -- )n                    a[i][j] -= a[r][j] * a[i][c];n        n        r ++ ;n    }n    n    if (r < n)n    {n        for (int i = r; i < n; i ++ )n            if (fabs(a[i][n]) > eps)n                return 2; // 无解n        return 1; // 有无穷多组解n    }n    n    for (int i = n - 1; i >= 0; i -- )n        for (int j = i + 1; j < n; j ++ )n            a[i][n] -= a[i][j] * a[j][n];n    n    return 0; // 有唯一解n}n",
    "description": "gauss - 高斯消元(浮点值)"
  },
  "gauss - 高斯消元(布尔值)": {
    "prefix": "int gauss",
    "body": "int gauss()  // 高斯消元,答案存于a[i][n]中,0 <= i < nn{n    int c, r;n    for (c = 0, r = 0; c < n; c ++ )n    {n        int t = r;n        for (int i = r; i < n; i ++ )  // 找非零行n            if (a[i][c])n                t = i;nn        if (!a[t][c]) continue;nn        for (int i = c; i <= n; i ++ ) swap(a[r][i], a[t][i]);  // 将非零行换到最顶端n        for (int i = r + 1; i < n; i ++ )  // 用当前行将下面所有的列消成0n            if (a[i][c])n                for (int j = n; j >= c; j -- )n                    a[i][j] ^= a[r][j];nn        r ++ ;n    }nn    if (r < n)n    {n        for (int i = r; i < n; i ++ )n            if (a[i][n])n                return 2;  // 无解n        return 1;  // 有多组解n    }nn    for (int i = n - 1; i >= 0; i -- )n        for (int j = i + 1; j < n; j ++ )n            a[i][n] ^= a[i][j] * a[j][n];nn    return 0;  // 有唯一解n}n",
    "description": "gauss - 高斯消元(布尔值)"
  },
  "int gcd - 欧几里得算法": {
    "prefix": "int gcd",
    "body": "int gcd(int a, int b)  // 欧几里得算法n{n    return b ? gcd(b, a % b) : a;n}n",
    "description": "int gcd - 欧几里得算法"
  },
  "LL gcd - 欧几里得算法": {
    "prefix": "LL gcd",
    "body": "LL gcd(LL a, LL b)  // 欧几里得算法n{n    return b ? gcd(b, a % b) : a;n}n",
    "description": "LL gcd - 欧几里得算法"
  },
  "int exgcd - 扩展欧几里得算法": {
    "prefix": "int exgcd",
    "body": "int exgcd(int a, int b, int &x, int &y)  // 扩展欧几里得算法, 求x, y,使得ax + by = gcd(a, b)n{n    if (!b)n    {n        x = 1; y = 0;n        return a;n    }n    int d = exgcd(b, a % b, y, x);n    y -= (a / b) * x;n    return d;n}n",
    "description": "int exgcd - 扩展欧几里得算法"
  },
  "int lucas - Lucas定理": {
    "prefix": "int lucas",
    "body": "int qmi(int a, int k, int p)  // 快速幂模板n{n    int res = 1 % p;n    while (k)n    {n        if (k & 1) res = (LL)res * a % p;n        a = (LL)a * a % p;n        k >>= 1;n    }n    return res;n}nnint C(int a, int b, int p)  // 通过定理求组合数C(a, b)n{n    if (a < b) return 0;nn    LL x = 1, y = 1;  // x是分子,y是分母n    for (int i = a, j = 1; j <= b; i --, j ++ )n    {n        x = (LL)x * i % p;n        y = (LL) y * j % p;n    }nn    return x * (LL)qmi(y, p - 2, p) % p;n}nnint lucas(LL a, LL b, int p)n{n    if (a < p && b < p) return C(a, b, p);n    return (LL)C(a % p, b % p, p) * lucas(a / p, b / p, p) % p;n}n",
    "description": "int lucas - Lucas定理"
  },
  "bool is_prime - 判定质数": {
    "prefix": "bool is_prime",
    "body": "bool is_prime(int x)  // 判定质数n{n    if (x < 2) return false;n    for (int i = 2; i <= x / i; i ++ )n        if (x % i == 0)n            return false;n    return true;n}n",
    "description": "bool is_prime - 判定质数"
  },
  "void get_primes - 线性筛质数": {
    "prefix": "void get_primes",
    "body": "void get_primes(int n)  // 线性筛质数n{n    for (int i = 2; i <= n; i ++ )n    {n        if (!st[i]) primes[cnt ++ ] = i;n        for (int j = 0; primes[j] <= n / i; j ++ )n        {n            st[primes[j] * i] = true;n            if (i % primes[j] == 0) break;n        }n    }n}n",
    "description": "void get_primes - 线性筛质数"
  },
  "int qmi - 快速幂": {
    "prefix": "int qmi",
    "body": "int qmi(int a, int k, int p)  // 求a^k mod pn{n    int res = 1 % p;n    while (k)n    {n        if (k & 1) res = (LL)res * a % p;n        a = (LL)a * a % p;n        k >>= 1;n    }n    return res;n}n",
    "description": "int qmi - 快速幂"
  },
  "int quick_power - 快速幂": {
    "prefix": "int quick_power",
    "body": "int quick_power(int a, int k, int p)  // 求a^k mod pn{n    int res = 1 % p;n    while (k)n    {n        if (k & 1) res = (LL)res * a % p;n        a = (LL)a * a % p;n        k >>= 1;n    }n    return res;n}n",
    "description": "int quick_power - 快速幂"
  },
  "int main - 主函数": {
    "prefix": "int main",
    "body": "int main()n{n    $1n    return 0;n}",
    "description": "int main - 主函数"
  },
  "simulate_anneal - 模拟退火": {
    "prefix": "void simulate_anneal",
    "body": "double calc()n{n    // TODO: 计算当前方案的值n    n    ans = min(ans, res);  // 更新全局答案n    return res;n}nnvoid simulate_anneal()  // 模拟退火n{n    for (double t = 1e6; t > 1e-6; t *= 0.95)  // 逐渐降温n    {n        double x = calc();  // 原方案的值n        // TODO: 随机一个新方案n        double y = calc();  // 新方案的值n        double delta = y - x;n        n        // 新方案更好,则必选新方案;否则以一定概率选新方案 n        if (exp(-delta / t) > (double)rand() / RAND_MAX)n        {n            // TODO: 换成新方案n        }n    }n}n",
    "description": "simulate_anneal - 模拟退火"
  },
  "const int N = ": {
    "prefix": "const int",
    "body": "const int N = $1",
    "description": "const int N = "
  },
  "const double eps = 1e-8;": {
    "prefix": "const",
    "body": "const double eps = 1e-8;n",
    "description": "const double eps = 1e-8;"
  },
  "const double PI = acos(-1);": {
    "prefix": "const",
    "body": "const double PI = acos(-1);n",
    "description": "const double PI = acos(-1);"
  },
  "int h[N]...邻接表不带权": {
    "prefix": "int h",
    "body": "int h[N], e[M], ne[M], idx;n",
    "description": "int h[N]...邻接表不带权"
  },
  "int h[N]...邻接表spfa": {
    "prefix": "int h",
    "body": "int h[N], e[M], w[M], ne[M], idx;nint q[N], dist[N];nbool st[N];n",
    "description": "int h[N]...邻接表spfa"
  },
  "int h[N]...邻接表dijkstra": {
    "prefix": "int h",
    "body": "int h[N], e[M], w[M], ne[M], idx;nint dist[N];nbool st[N];n",
    "description": "int h[N]...邻接表dijkstra"
  },
  "int h[N]...邻接表最大流": {
    "prefix": "int h",
    "body": "int h[N], e[M], f[M], ne[M], idx;nint q[N], d[N], pre[N];nbool st[N];n",
    "description": "int h[N]...邻接表最大流"
  },
  "int h[N]...邻接表费用流": {
    "prefix": "int h",
    "body": "int h[N], e[M], f[M], w[M], ne[M], idx;nint q[N], d[N], pre[N], incf[N];nbool st[N];n",
    "description": "int h[N]...邻接表费用流"
  },
  "int h[N]...邻接表tarjan-scc": {
    "prefix": "int h",
    "body": "int h[N], e[M], ne[M], idx;nint dfn[N], low[N], timestamp;  // 时间戳nint stk[N], top;nbool in_stk[N];nint id[N], scc_cnt;  // 每个点所属分量编号n",
    "description": "int h[N]...邻接表tarjan-scc"
  },
  "int h[N]...邻接表tarjan-e-dcc": {
    "prefix": "int h",
    "body": "int h[N], e[M], ne[M], idx;nint dfn[N], low[N], timestamp;  // 时间戳nint stk[N], top;nint id[N], dcc_cnt;  // 每个点所属分量编号nbool is_bridge[M];n",
    "description": "int h[N]...邻接表tarjan-e-dcc"
  },
  "int h[N]...邻接表tarjan-v-dcc": {
    "prefix": "int h",
    "body": "int h[N], e[M], ne[M], idx;nint dfn[N], low[N], timestamp;  // 时间戳nint stk[N], top;nint dcc_cnt;nvector dcc[N];  // 每个分量有哪些点nbool cut[N];  // 是否为割点nint root;n",
    "description": "int h[N]...邻接表tarjan-v-dcc"
  },
  "#define x first": {
    "prefix": "#define",
    "body": "#define x firstn",
    "description": "#define x first"
  },
  "#define y second": {
    "prefix": "#define",
    "body": "#define y secondn",
    "description": "#define y second"
  },
  "#include - 常用头文件": {
    "prefix": "#include",
    "body": "#include n#include n#include n",
    "description": "#include - 常用头文件"
  },
  "#include ": {
    "prefix": "#include",
    "body": "#include n",
    "description": "#include "
  },
  "#include ": {
    "prefix": "#include",
    "body": "#include n",
    "description": "#include "
  },
  "#include ": {
    "prefix": "#include",
    "body": "#include n",
    "description": "#include "
  },
  "#include ": {
    "prefix": "#include",
    "body": "#include n",
    "description": "#include "
  },
  "#include ": {
    "prefix": "#include",
    "body": "#include n",
    "description": "#include "
  },
  "#include ": {
    "prefix": "#include",
    "body": "#include n",
    "description": "#include "
  },
  "#include ": {
    "prefix": "#include",
    "body": "#include n",
    "description": "#include "
  },
  "#include ": {
    "prefix": "#include",
    "body": "#include n",
    "description": "#include "
  },
  "#pragma GCC optimize(2)": {
    "prefix": "#p",
    "body": "#pragma GCC optimize(2)n",
    "description": "#pragma GCC optimize(2)"
  },
  "#pragma GCC optimize(3)": {
    "prefix": "#p",
    "body": "#pragma GCC optimize(3)n",
    "description": "#pragma GCC optimize(3)"
  },
  "typedef long long LL;": {
    "prefix": "typedef",
    "body": "typedef long long LL;n",
    "description": "typedef long long LL;"
  },
  "typedef pair PII;": {
    "prefix": "typedef",
    "body": "typedef pair PII;n",
    "description": "typedef pair PII;"
  },
  "typedef pair PDD;": {
    "prefix": "typedef",
    "body": "typedef pair PDD;n",
    "description": "typedef pair PDD;"
  },
  "typedef unsigned long long ULL;": {
    "prefix": "typedef",
    "body": "typedef unsigned long long ULL;n",
    "description": "typedef unsigned long long ULL;"
  },
  "using namespace std;": {
    "prefix": "using",
    "body": "using namespace std;n",
    "description": "using namespace std;"
  },
  "scanf one": {
    "prefix": "scanf",
    "body": "scanf("%d",&$1);n",
    "description": "scanf 输入一个数"
  },
  "scanf tow": {
    "prefix": "scanf",
    "body": "scanf("%d%d",&$1, &$2);n",
    "description": "scanf 输入两个数"
  },
  "int n, m;": {
    "prefix": "int n, m",
    "body": "int n, m;n",
    "description": "定义两个数"
  },

}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/766695.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号