├── README.md ├── 图论 ├── 拓扑排序 │ ├── README.md │ └── topo.cc └── 最短路 │ ├── README.md │ ├── a_star.cc │ ├── bfs.cc │ ├── dfs.cc │ ├── dfs_path.cc │ ├── dijkstra.cc │ ├── dijkstra_set.cc │ ├── floyd.cc │ ├── mould.cc │ └── spfa.cc ├── 基础算法 ├── README.md └── 二分 │ ├── README.md │ ├── binary_search_1.cc │ ├── binary_search_2.cc │ ├── binary_search_3.cc │ ├── binary_search_4.cc │ ├── binary_search_5.cc │ └── binary_search_6.cc └── 数据结构 ├── LCA └── lac.cc ├── RMQ └── rmq.cc ├── sort ├── README.md ├── heap.cc ├── maopao.cc ├── merge.cc └── sort.cc ├── 并查集 ├── README.md └── union.cc └── 树状数组 └── a.cc /README.md: -------------------------------------------------------------------------------- 1 | # 算法总结 2 | 3 | - 基础算法 4 | - 时间复杂度 5 | - 枚举 6 | - 模拟 7 | - 二分 8 | - 贪心 9 | - 数组的使用 10 | - 基础数学 11 | - 分治 12 | - 倍增 13 | - 随机 14 | - 分块 15 | - 离散化 16 | - 搜索 17 | 18 | - 图论算法 19 | - 拓扑排序 20 | - DAG 21 | - 最小生成树 22 | - 欧拉路,哈密顿路 23 | - 最短路 24 | - 连通性 25 | - 查分约束 26 | - 2-SAT 27 | - 网络流 28 | - 二分图匹配 29 | - 数学 30 | - 数论 31 | - 快速幂 32 | - 质数 33 | - 约束 34 | - 大数 35 | - 同余定理 36 | - FFT 37 | - 扩展欧几里得 38 | - 博弈论 39 | - 概率论 40 | - 几何数学 41 | - 线性代数 42 | - 矩阵快速幂 43 | - 高斯消元 44 | - 线性规划 45 | - 组合数学 46 | - 组合计数 47 | - 几种特殊的计数序列 48 | - 康拓展开,康拓逆展开 49 | - 容斥原理 50 | - 卢卡斯定理 51 | - 莫比乌斯反演 52 | - Polya 定理 53 | - 数据结构 54 | - STL 55 | - 排序 56 | - 并查集 57 | - 树状数组 58 | - 线段树 59 | - RMQ 问题 60 | - LCA 61 | - 树链剖分 62 | - 平衡树 63 | - 动态树 64 | - 红黑树 65 | - B 树,B+ 树 66 | - 字符串算法 67 | - 哈希和哈希表 68 | - KMP 和 扩展 KMP 69 | - Trie 字典树 70 | - AC 自动机 71 | - 后缀数组、后缀自动机 72 | - 动态规划 73 | - 基本的动态规划模型 74 | - 背包问题 75 | - 区间动态规划 76 | - 树形动态规划 77 | - 数为动态规划 78 | - 状态压缩动态规划 79 | - 单调队列动态规划 80 | - 斜率优化动态规划 81 | -------------------------------------------------------------------------------- /图论/拓扑排序/README.md: -------------------------------------------------------------------------------- 1 | ### 算法流程 2 | 3 | 拓扑排序算法主要由以下两步循环执行,直到不存在入度为 $0$ 的顶点为止。 4 | 5 | 1. 选择一个入度为 $0$ 的顶点并将它输出; 6 | 2. 删除图中从顶点连出的所有边。 7 | 8 | 循环结束,若输出的顶点数小于图中的顶点数,则表示该图中存在回路,也就是无法进行拓扑排序;否则输出的顶点序列就是一个拓扑序列。 9 | 10 | 时间复杂度 $\mathcal{O}(E + V)$ 11 | -------------------------------------------------------------------------------- /图论/拓扑排序/topo.cc: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const long long MAX_N = 500005; 4 | const long long MAX_M = 500005; 5 | queue q; 6 | struct edge { 7 | long long v, next; 8 | long long len; 9 | } e[MAX_M]; 10 | long long p[MAX_N], eid; 11 | void init() { 12 | memset(p, -1, sizeof(p)); 13 | eid = 0; 14 | } 15 | void insert(long long u, long long v) { 16 | e[eid].v = v; 17 | e[eid].next = p[u]; 18 | p[u] = eid++; 19 | } 20 | long long chu[5005]; 21 | long long ru[5005]; 22 | long long f[5005]; 23 | int main() { 24 | init(); 25 | long long n, m; 26 | cin >> n >> m; 27 | for(int i = 0; i < m; i++) { 28 | int u, v; 29 | cin >> u >> v; 30 | insert(u, v); 31 | chu[u]++; 32 | ru[v]++; 33 | } 34 | for(int i = 1; i <= n; i++){ 35 | if(ru[i] == 0){ 36 | f[i] = 1; 37 | q.push(i); 38 | } 39 | } 40 | long long ans = 0; 41 | while(!q.empty()){ 42 | int u = q.front(); 43 | q.pop(); 44 | for(int i = p[u]; i != -1; i = e[i].next){ 45 | int b = e[i].v;//�ӽڵ� 46 | f[b] += f[u]; 47 | ru[b]--; 48 | if(chu[b] == 0){ 49 | ans += f[u]; 50 | } 51 | if (!ru[b]) { 52 | q.push(b); 53 | } 54 | } 55 | } 56 | cout << ans << endl; 57 | return 0; 58 | } 59 | 60 | // https://www.luogu.com.cn/problem/P4017 61 | -------------------------------------------------------------------------------- /图论/最短路/README.md: -------------------------------------------------------------------------------- 1 | # 最短路算法 2 | 3 | [题目测试连接](http://acm.hdu.edu.cn/showproblem.php?pid=2544) 4 | 5 | - DFS 6 | - BFS 7 | - BFS (拆点方法) 8 | - Floyd 9 | - SPFA 10 | - Dijkstra (优先队列) 11 | - Dijkstra_set (堆优化) 12 | - A* (图,太稠密,这道题通不过) 13 | - Hill Climbing (爬山算法) 14 | - SA,Simulated Annealing (模拟退火) 15 | 16 | 17 | - DFS 记录路径 18 | -------------------------------------------------------------------------------- /图论/最短路/a_star.cc: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int N = 1e2 + 9; 4 | const int M = 2e4 + 9; 5 | const int inf = 0x3f3f3f3f; 6 | 7 | struct edge { 8 | int v, w, next; 9 | } e[M]; 10 | int p[N], eid; 11 | void init() 12 | { 13 | memset(p, -1, sizeof p); 14 | eid = 0; 15 | } 16 | void add(int u, int v, int w) 17 | { 18 | e[eid].v = v; 19 | e[eid].w = w; 20 | e[eid].next = p[u]; 21 | p[u] = eid++; 22 | } 23 | struct node { 24 | int u, dis; 25 | friend bool operator < (const node a, const node b) { 26 | if (a.dis != b.dis) { 27 | return a.dis > b.dis; 28 | } 29 | return a.u < b.u; 30 | } 31 | }; 32 | int g[N]; // g[i] 表示估计未来的长度,g[i] 表示从 i 到 n 的距离 33 | void dijkstra(int u) 34 | { 35 | memset(g, inf, sizeof g); 36 | g[u] = 0; 37 | set q; 38 | q.insert((node){u, 0}); 39 | while (!q.empty()) { 40 | node now = (*q.begin()); 41 | q.erase(q.begin()); 42 | u = now.u; 43 | for (int i = p[u]; ~i; i = e[i].next) { 44 | int v = e[i].v; 45 | int w = e[i].w; 46 | if (g[v] > g[u] + w) { 47 | q.erase((node){v, g[v]}); 48 | g[v] = g[u] + w; 49 | q.insert((node){v, g[v]}); 50 | } 51 | } 52 | } 53 | } 54 | struct data { 55 | int u; 56 | int dis; // dis 表示已经走过的路径长度 57 | bool vis[N]; 58 | friend bool operator < (const data a, const data b) { 59 | return a.dis + g[a.u] > b.dis + g[b.u]; 60 | } 61 | }; 62 | int a_star(int u, int n) 63 | { 64 | int cnt = 0; 65 | priority_queue q; 66 | data s; 67 | s.u = u; 68 | s.dis = 0; 69 | memset(s.vis, false, sizeof s.vis); 70 | s.vis[u] = true; 71 | q.push(s); 72 | while (!q.empty()) { 73 | s = q.top(); 74 | q.pop(); 75 | if (s.u == n) { 76 | cnt++; 77 | if (cnt == 1) { // 第一短路的意思 78 | return s.dis; 79 | } 80 | } 81 | for (int i = p[u]; ~i; i = e[i].next) { 82 | int v = e[i].v; 83 | int w = e[i].w; 84 | if (s.vis[v]) { 85 | continue; 86 | } 87 | data tmp = s; 88 | tmp.u = v; 89 | tmp.dis = s.dis + w; 90 | tmp.vis[v] = true; 91 | q.push(tmp); 92 | } 93 | } 94 | return -1; 95 | } 96 | int main() 97 | { 98 | int n; 99 | int m; 100 | while (cin >> n >> m, n | m) { 101 | init(); 102 | while (m--) { 103 | int u, v, w; 104 | cin >> u >> v >> w; 105 | add(u, v, w); 106 | add(v, u, w); 107 | } 108 | dijkstra(n); // 如果是有向图,需要构建反向图,求出预估值 g 109 | cout << a_star(1, n) << endl; 110 | } 111 | return 0; 112 | } 113 | -------------------------------------------------------------------------------- /图论/最短路/bfs.cc: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int N = 1e2 + 9; 4 | const int M = 2e4 + 9; 5 | const int inf = 0x3f3f3f3f; 6 | 7 | struct edge { 8 | int v; 9 | int w; 10 | int next; 11 | } e[M]; 12 | 13 | int p[N], eid; 14 | void init() 15 | { 16 | eid = 0; 17 | memset(p, -1, sizeof p); 18 | } 19 | void add(int u, int v, int w) 20 | { 21 | e[eid].v = v; 22 | e[eid].w = w; 23 | e[eid].next = p[u]; 24 | p[u] = eid++; 25 | } 26 | 27 | int dis[N]; 28 | void bfs(int u) 29 | { 30 | memset(dis, inf, sizeof dis); 31 | dis[u] = 0; 32 | queue q; 33 | q.push(u); 34 | while (!q.empty()) { 35 | u = q.front(); 36 | q.pop(); 37 | for (int i = p[u]; ~i; i = e[i].next) { 38 | int v = e[i].v; 39 | int w = e[i].w; 40 | if (dis[v] > dis[u] + w) { 41 | dis[v] = dis[u] + w; 42 | q.push(v); 43 | } 44 | } 45 | } 46 | } 47 | 48 | int main() 49 | { 50 | int n; 51 | int m; 52 | while (cin >> n >> m, n | m) { 53 | init(); 54 | while (m--) { 55 | int u, v, w; 56 | cin >> u >> v >> w; 57 | add(u, v, w); 58 | add(v, u, w); 59 | } 60 | bfs(1); 61 | cout << dis[n] << endl; 62 | } 63 | return 0; 64 | } 65 | -------------------------------------------------------------------------------- /图论/最短路/dfs.cc: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int N = 1e2 + 9; 4 | const int M = 2e4 + 9; 5 | const int inf = 0x3f3f3f3f; 6 | 7 | struct edge { 8 | int v; 9 | int w; 10 | int next; 11 | } e[M]; 12 | 13 | int p[N], eid; 14 | int dis[N]; 15 | void init() 16 | { 17 | eid = 0; 18 | memset(p, -1, sizeof p); 19 | memset(dis, inf, sizeof dis); 20 | } 21 | void add(int u, int v, int w) 22 | { 23 | e[eid].v = v; 24 | e[eid].w = w; 25 | e[eid].next = p[u]; 26 | p[u] = eid++; 27 | } 28 | 29 | void dfs(int u) 30 | { 31 | for (int i = p[u]; ~i; i = e[i].next) { 32 | int v = e[i].v; 33 | int w = e[i].w; 34 | if (dis[v] > dis[u] + w) { 35 | dis[v] = dis[u] + w; 36 | dfs(v); 37 | } 38 | } 39 | } 40 | 41 | int main() 42 | { 43 | int n; 44 | int m; 45 | while (cin >> n >> m, n | m) { 46 | init(); 47 | while (m--) { 48 | int u, v, w; 49 | cin >> u >> v >> w; 50 | add(u, v, w); 51 | add(v, u, w); 52 | } 53 | dis[1] = 0; 54 | dfs(1); 55 | cout << dis[n] << endl; 56 | } 57 | return 0; 58 | } 59 | -------------------------------------------------------------------------------- /图论/最短路/dfs_path.cc: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int N = 1e2 + 9; 4 | const int M = 2e4 + 9; 5 | const int inf = 0x3f3f3f3f; 6 | 7 | struct edge { 8 | int v; 9 | int w; 10 | int next; 11 | } e[M]; 12 | 13 | int p[N], eid; 14 | int dis[N]; 15 | int fa[N]; 16 | void init() 17 | { 18 | eid = 0; 19 | memset(p, -1, sizeof p); 20 | memset(dis, inf, sizeof dis); 21 | for (int i = 0; i < N; i++) { 22 | fa[i] = i; 23 | } 24 | } 25 | void add(int u, int v, int w) 26 | { 27 | e[eid].v = v; 28 | e[eid].w = w; 29 | e[eid].next = p[u]; 30 | p[u] = eid++; 31 | } 32 | 33 | void dfs(int u) 34 | { 35 | for (int i = p[u]; ~i; i = e[i].next) { 36 | int v = e[i].v; 37 | int w = e[i].w; 38 | if (dis[v] > dis[u] + w) { 39 | dis[v] = dis[u] + w; 40 | fa[v] = u; 41 | dfs(v); 42 | } 43 | } 44 | } 45 | 46 | void print(int u) 47 | { 48 | if (fa[u] == u) { 49 | cout << u; 50 | return; 51 | } 52 | print(fa[u]); 53 | cout << " -> " << u; 54 | } 55 | 56 | int main() 57 | { 58 | int n; 59 | int m; 60 | while (cin >> n >> m, n | m) { 61 | init(); 62 | while (m--) { 63 | int u, v, w; 64 | cin >> u >> v >> w; 65 | add(u, v, w); 66 | add(v, u, w); 67 | } 68 | dis[1] = 0; 69 | dfs(1); 70 | print(n); 71 | cout << endl << dis[n] << endl; 72 | } 73 | return 0; 74 | } 75 | -------------------------------------------------------------------------------- /图论/最短路/dijkstra.cc: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int N = 1e5 + 9; 4 | const int M = 2e5 + 9; 5 | const int inf = 0x3f3f3f3f; 6 | 7 | struct edge { 8 | int v, w, next; 9 | } e[M]; 10 | int p[N], eid; 11 | void init() 12 | { 13 | memset(p, -1, sizeof p); 14 | eid = 0; 15 | } 16 | void add(int u, int v, int w) 17 | { 18 | e[eid].v = v; 19 | e[eid].w = w; 20 | e[eid].next = p[u]; 21 | p[u] = eid++; 22 | } 23 | struct node { 24 | int u, dis; 25 | bool operator < (const node b) const { 26 | if (dis != b.dis) { 27 | return dis > b.dis; 28 | } 29 | return u < b.u; 30 | } 31 | }; 32 | int dis[N] ; 33 | void dijkstra(int u) 34 | { 35 | memset(dis, inf, sizeof dis); 36 | dis[u] = 0; 37 | priority_queue q; 38 | q.push((node){u, 0}); 39 | while (!q.empty()) { 40 | node now = q.top(); 41 | q.pop(); 42 | u = now.u; 43 | for (int i = p[u]; ~i; i = e[i].next) { 44 | int v = e[i].v; 45 | int w = e[i].w; 46 | if (dis[v] > dis[u] + w) { 47 | dis[v] = dis[u] + w; 48 | q.push((node){v, dis[v]}); 49 | } 50 | } 51 | } 52 | } 53 | int main() 54 | { 55 | int n; 56 | int m; 57 | while (cin >> n >> m, n | m) { 58 | init(); 59 | while (m--) { 60 | int u, v, w; 61 | cin >> u >> v >> w; 62 | add(u, v, w); 63 | add(v, u, w); 64 | } 65 | dijkstra(1); 66 | cout << dis[n] << endl; 67 | } 68 | return 0; 69 | } 70 | -------------------------------------------------------------------------------- /图论/最短路/dijkstra_set.cc: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int N = 1e5 + 9; 4 | const int M = 2e5 + 9; 5 | const int inf = 0x3f3f3f3f; 6 | 7 | struct edge { 8 | int v, w, next; 9 | } e[M]; 10 | int p[N], eid; 11 | void init() 12 | { 13 | memset(p, -1, sizeof p); 14 | eid = 0; 15 | } 16 | void add(int u, int v, int w) 17 | { 18 | e[eid].v = v; 19 | e[eid].w = w; 20 | e[eid].next = p[u]; 21 | p[u] = eid++; 22 | } 23 | struct node { 24 | int u, dis; 25 | bool operator < (const node b) const { 26 | if (dis != b.dis) { 27 | return dis > b.dis; 28 | } 29 | return u < b.u; 30 | } 31 | }; 32 | int dis[N] ; 33 | void dijkstra(int u) 34 | { 35 | memset(dis, inf, sizeof dis); 36 | dis[u] = 0; 37 | set q; 38 | q.insert((node){u, 0}); 39 | while (!q.empty()) { 40 | node now = (*q.begin()); 41 | q.erase(q.begin()); 42 | u = now.u; 43 | for (int i = p[u]; ~i; i = e[i].next) { 44 | int v = e[i].v; 45 | int w = e[i].w; 46 | if (dis[v] > dis[u] + w) { 47 | q.erase((node){v, dis[v]}); 48 | dis[v] = dis[u] + w; 49 | q.insert((node){v, dis[v]}); 50 | } 51 | } 52 | } 53 | } 54 | int main() 55 | { 56 | int n; 57 | int m; 58 | while (cin >> n >> m, n | m) { 59 | init(); 60 | while (m--) { 61 | int u, v, w; 62 | cin >> u >> v >> w; 63 | add(u, v, w); 64 | add(v, u, w); 65 | } 66 | dijkstra(1); 67 | cout << dis[n] << endl; 68 | } 69 | return 0; 70 | } 71 | -------------------------------------------------------------------------------- /图论/最短路/floyd.cc: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | const int N = 1e2 + 9; 5 | const int inf = 0x3f3f3f3f; 6 | int n; 7 | int m; 8 | int f[N][N]; 9 | 10 | void floyd() 11 | { 12 | for (int k = 1; k <= n; k++) { 13 | for (int i = 1; i <= n; i++) { 14 | for (int j = 1; j <= n; j++) { 15 | f[i][j] = min(f[i][j], f[i][k] + f[k][j]); 16 | } 17 | } 18 | } 19 | return; 20 | } 21 | 22 | int main() 23 | { 24 | while (cin >> n >> m, n | m) { 25 | memset(f, inf, sizeof f); 26 | for (int i = 0; i < m; i++) { 27 | int u, v, w; 28 | cin >> u >> v >> w; 29 | f[u][v] = f[v][u] = w; 30 | } 31 | floyd(); 32 | cout << f[1][n] << endl; 33 | } 34 | return 0; 35 | } 36 | -------------------------------------------------------------------------------- /图论/最短路/mould.cc: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int N = 1e2 + 9; 4 | const int N = 2e2 + 9; 5 | const int inf = 0x3f3f3f3f; 6 | 7 | struct edge { 8 | int v; 9 | int w; 10 | int next; 11 | } e[M]; 12 | 13 | int p[N], eid; 14 | void init() 15 | { 16 | eid = 0; 17 | memset(p, -1, sizeof p); 18 | } 19 | void add(int u, int v, int w) 20 | { 21 | e[eid].v = v; 22 | e[eid].w = w; 23 | e[eid].next = p[u]; 24 | p[u] = eid++; 25 | } 26 | 27 | int main() 28 | { 29 | int n; 30 | int m; 31 | while (cin >> n >> m, n | m) { 32 | init(); 33 | while (m--) { 34 | int u, v, w; 35 | cin >> u >> v >> w; 36 | add(u, v, w); 37 | add(v, u, w); 38 | } 39 | } 40 | return 0; 41 | } 42 | -------------------------------------------------------------------------------- /图论/最短路/spfa.cc: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int N = 1e2 + 9; 4 | const int M = 2e4 + 9; 5 | const int inf = 0x3f3f3f3f; 6 | 7 | struct edge { 8 | int v; 9 | int w; 10 | int next; 11 | } e[M]; 12 | 13 | int p[N], eid; 14 | void init() 15 | { 16 | eid = 0; 17 | memset(p, -1, sizeof p); 18 | } 19 | void add(int u, int v, int w) 20 | { 21 | e[eid].v = v; 22 | e[eid].w = w; 23 | e[eid].next = p[u]; 24 | p[u] = eid++; 25 | } 26 | 27 | int dis[N]; 28 | bool vis[N]; 29 | void spfa(int u) 30 | { 31 | memset(vis, false, sizeof vis); 32 | vis[u] = true; 33 | memset(dis, inf, sizeof dis); 34 | dis[u] = 0; 35 | queue q; 36 | q.push(u); 37 | while (!q.empty()) { 38 | u = q.front(); 39 | q.pop(); 40 | vis[u] = false; 41 | for (int i = p[u]; ~i; i = e[i].next) { 42 | int v = e[i].v; 43 | int w = e[i].w; 44 | if (dis[v] > dis[u] + w) { 45 | dis[v] = dis[u] + w; 46 | if (!vis[v]) { 47 | vis[v] = true; 48 | q.push(v); 49 | } 50 | } 51 | } 52 | } 53 | return; 54 | } 55 | 56 | int main() 57 | { 58 | int n; 59 | int m; 60 | while (cin >> n >> m, n | m) { 61 | init(); 62 | while (m--) { 63 | int u, v, w; 64 | cin >> u >> v >> w; 65 | add(u, v, w); 66 | add(v, u, w); 67 | } 68 | spfa(1); 69 | cout << dis[n] << endl; 70 | } 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /基础算法/README.md: -------------------------------------------------------------------------------- 1 | # 基础算法 2 | 3 | [toc] 4 | 5 | 通用思维:正向,逆行 6 | 7 | 计算机思维:有条理的 枚举 + 模拟 8 | 9 | 有条理: 10 | - 减少变量 11 | - 降维 12 | - 先暴力,后优化 13 | - 问题抽象话,转化为可以算法套用的 14 | 15 | **贪心**,**二分**,枚举,模拟,搜索 16 | 17 | ### 时间复杂度 18 | 在竞赛中,我们认为计算机一秒能执行 $5\times 10^8$ 次计算,如果题目给出的时间限制为 $1s$,那么你选择的算法执行的计算次数最多应该在 $10^8$ 量级才有可能解决这个题目。 19 | 20 | - $\mathcal{O}(1)$ 21 | - $\mathcal{O}(\log n)$ 22 | - 快速幂 23 | - $\mathcal{O}(n)$ ($n$ 的数据范围一般是 $n \le 10^8$) 24 | - 数组中元素的查找,删除 25 | - $\mathcal{O}(n \log n)$ ($n$ 的数据范围一般是 $n \le 10^6$) 26 | - 快排(贪心) 27 | - 质数筛思想 28 | - $\mathcal{O}(n \sqrt{n})$ ($n$ 的数据范围一般是 $n \le 10^5$) 29 | - 判断一个数是否是质数 30 | - $\mathcal{O}(n^2)$ ($n$ 的数据范围一般是 $n \le 5000$) 31 | - 冒泡排序 32 | - $\mathcal{O}(n^3)$ ($n$ 的数据范围一般是 $n \le 300$) 33 | - 三层 for 循环(弗洛里得算法) 34 | - $\mathcal{O}(2^n)$ ($n$ 的数据范围一般是 $n \le 25$) 35 | - 二进制枚举 36 | - $\mathcal{O}(n!)$ ($n$ 的数据范围一般是 $n \le 11$) 37 | - 全排列 38 | 39 | ### 枚举 40 | 先假设答案,然后校验 41 | - [百钱买百鸡](https://nanti.jisuanke.com/t/T1372) 42 | - [鸡兔同笼](https://nanti.jisuanke.com/t/T1191) 43 | - [滑雪课程设计](https://nanti.jisuanke.com/t/T1893) 44 | 45 | ### 模拟 46 | - [青蛙爬井](https://nanti.jisuanke.com/t/T1376) 47 | - [七桥问题](https://nanti.jisuanke.com/t/T1545) 48 | - [汽水瓶](https://nanti.jisuanke.com/t/T1509) 49 | - ![](https://oitiku.sh1a.qingstor.com/11.jpg) 50 | - 日期问题 51 | - date 数组 52 | - dx,dy 53 | - 表达式求值 54 | 55 | ### 二分 56 | - 二分查找 57 | - 二分答案 58 | - [跳石头](https://nanti.jisuanke.com/t/T2028) 59 | 60 | 61 | 62 | ### 贪心 63 | - 会议安排 64 | - 最小的名字 65 | - [均分纸牌](https://nanti.jisuanke.com/t/T2158) 66 | 67 | ### 数组的使用 68 | - 桶排序 69 | - [校门外的树](https://nanti.jisuanke.com/t/T2128) 70 | - 纸牌游戏 71 | - 大数加法、减法、乘法 72 | - 大数取模 73 | - [懒人标记](https://blog.csdn.net/qq276291420/article/details/9347655) 74 | - 前缀和 75 | - 打表法——质数筛 (预处理)(极端:本地打表) 76 | - 环上的问题 77 | 78 | ### 基础数学 79 | - 最大公约数,最小公倍数及其相关性质 80 | - 同余定理 81 | - 质数问题 82 | - 快速幂 83 | - 进制转换 84 | - 欧拉函数 85 | 86 | 87 | 88 | 89 | ### 小技巧 90 | - 初始值 0x3f3f3f3f,最大值 0x3f3f3f3f 91 | - while(~scanf()) 92 | - o(2) 优化 93 | - scanf / printf 94 | ``` 95 | scanf(); printf(); 96 | 97 | string s; 98 | cin.tie(0); 99 | cin.sync_with_stdio(false); 100 | 101 | 102 | int %d 103 | long long %lld 104 | double %f 105 | char %c // 会接收空格,回车 106 | char* %s // 不会接收空格回车 107 | scanf("%c.%c\n", &c, &c); // 这了可以抵消 108 | 109 | a + 0.5 110 | printf(".2f\n", a); 111 | printf("%2d%2d\n", a, a); // 右对齐 112 | printf("%-2d%-2d\n", a, a);// 左对齐 113 | printf("%02d%02d\n", a, a);// 占两位,不足补零 114 | 115 | #define p(x) printf(#x" = %d\n", x) 116 | 117 | sprintf() 118 | ``` 119 | 120 | - OJ 反馈结果 121 | ``` 122 | 1:Compiling:正在编译 123 | 2:Accepted:正确通过 124 | 3:Wrong Answer:答案错误 125 | 4:Time Limit Exceeded:超时 (:代码运行效率太低,循环写死,递归写死 126 | 5:Memory Limit Exceeded:超内存 (:数组开的太大,或者递归写死 127 | 6:Output Limit Exceeded:输出超限 (:循环写死,或者打印日志没有删除 128 | 7:Segmentation Fault:段错误 (:数组访问越界(可能有数据没有初始化),有时候也可能数组太大,递归写死 129 | 8:Compilation Error:编译错误 (:自己看编译错误信息 130 | 9:Presentation Error:格式错误 (:答案正确,可能多输出空格 131 | ``` 132 | 133 | - Debug 134 | ```cpp 135 | 打印中间变量(打印日志) 136 | 137 | 1:先根据反馈结果推断(段错误) 138 | 2:猜测自己是哪里错误,仔细看看(再读一读代码) 139 | 3:确定题目没有读错,判断读入是否有问题(先保证,Debug 前面的代码是正确的) 140 | 4:开始 打印日志 Debug() 141 | 142 | 二分 Debug 中间添加 return 0 查看 143 | ``` 144 | 145 | - 编译错误 146 | ``` 147 | 1:先看哪一行错误,找问题 148 | 2:看编译错误信息,比如说 \357, 那么就应该是中英文符号问题 149 | 3:百度翻译编译错误信息, 150 | 4:百度返回的错误信息 151 | 5:再问别人,给错误信息 152 | ``` 153 | 154 | - 比赛注意事项 155 | ``` 156 | 1. 认真读题 157 | - 读懂题意,可以理解样例 158 | - 数据范围,决定使用什么数据类型(:**建议只使用 long long double、 数组开大一些** 159 | - 倒推题意,思考是什么时间复杂度 160 | 2. 骗分方法 161 | - if 样例输出 162 | - cout 可能答案输出 163 | - 暴力得分 164 | - if 数据范围分类输出、cout、暴力、结合 165 | 3. 确保提交文件的正确性 166 | - 文件读写错误 freopen() 167 | - 一定要注意编译环境,不少缺少头文件 168 | 169 | 4. 数据的初始化 170 | - 数据一定要看好是在哪初始化,是否需要反复初始化 171 | - 全局变量,std 定义的时候,都是已经初始化好的 172 | 173 | 5. 边界问题(:检查的时候 174 | - 除以0的问题 175 | - 数组访问边界(-1, 1, 0,n) 176 | - 数据处理边界 ——特殊值 177 | 178 | 6. 慎重的问题 179 | - 遇到除法,乘法的时候,一定要注意 180 | - 遇到小数的时候,一定要注意精度问题,如果可以尽量使用 181 | - 字符串的接收 182 | 183 | 7. 合理的安排考试时间 184 | - 保证每道题都有代码 185 | 186 | - 自己在写代码常犯的错误,运算优先级问题,不要舍不得括号的使用 例如搜索时候的标记 187 | - if (=) == 188 | - 良好的代码风格,代码注释 189 | - 不要舍不得定义中间变量 190 | - 输出的是 `YES` 还是 `Yes` 还是 `yes` 191 | - 数组一定要注意自己的下标是 0 - (n -1) 还是 1 - n 192 | ``` 193 | 194 | ### 搜索 195 | ```c++ 196 | 出口、标记、枚举 197 | #include 198 | using namespace std; 199 | char mp[10][10];/* 200 | S**. 201 | .... 202 | ***T 203 | */ 204 | int vis[10][10]; 205 | // u d l r 206 | int dx[] = {-1, 1, 0, 0}; 207 | int dy[] = {0, 0, -1, 1}; 208 | int n, m; 209 | int dfs(int x, int y) { 210 | if (mp[x][y] == 'T') {// 出口 并不是每次都有 211 | return 1; 212 | } 213 | vis[x][y] = 1; // 两种标记方式 标记 mp[x][y] = '*'; 214 | for (int i = 0; i < 4; i++) { // 枚举,朝各个方向枚举 215 | int tx = x + dx[i]; // 更新状态 216 | int ty = y + dy[i]; // 更新状态 217 | if (tx >= 0 && tx < n && ty >= 0 && ty < m && // 没出边界 218 | mp[tx][ty] != '*' && vis[tx][ty] == 0) { // 这个点没有走过、并且可以走 219 | int flag = dfs(tx, ty); // 循环 (tx, ty) 是否可以走到终点 220 | if (flag == 1) { // 如果可以走 1 如果不能走到终点 0 221 | return 1; 222 | } 223 | } 224 | } 225 | return 0; 226 | } 227 | ``` 228 | 229 | 230 | - 倍增(快进多少倍) 231 | - 随机 232 | - 离散化 233 | - 分块 234 | 235 | https://blog.csdn.net/qq_39861188/article/details/84191528 236 | 237 | https://www.cnblogs.com/zxjhaha/p/11231914.html -------------------------------------------------------------------------------- /基础算法/二分/README.md: -------------------------------------------------------------------------------- 1 | # 二分 2 | 3 | ## 二分查找 4 | 5 | - https://nanti.jisuanke.com/t/T1560 6 | - https://nanti.jisuanke.com/t/T1561 7 | - https://nanti.jisuanke.com/t/T1562 8 | - https://nanti.jisuanke.com/t/T1563 9 | - https://nanti.jisuanke.com/t/T1555 10 | - https://nanti.jisuanke.com/t/T1556 11 | 12 | ## 二分应用 13 | 14 | ## 三分 15 | -------------------------------------------------------------------------------- /基础算法/二分/binary_search_1.cc: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int N = 1e5 + 9; 4 | int a[N]; 5 | 6 | int cal(int l, int r, int x) 7 | { 8 | while (l <= r) { 9 | int mid = (l + r) >> 1; 10 | if (a[mid] == x) { 11 | return 1; 12 | } 13 | if (a[mid] > x) { 14 | r = mid - 1; 15 | } else { 16 | l = mid + 1; 17 | } 18 | } 19 | return 0; 20 | } 21 | 22 | int main() 23 | { 24 | int n; 25 | int m; 26 | scanf("%d %d", &n, &m); 27 | for (int i = 0; i < n; i++) { 28 | scanf("%d", &a[i]); 29 | } 30 | sort(a, a + n); 31 | while (m--) { 32 | int x; 33 | scanf("%d", &x); 34 | if (cal(0, n - 1, x)) { 35 | puts("YES"); 36 | } else { 37 | puts("NO"); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /基础算法/二分/binary_search_2.cc: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | const int N = 1e5 + 9; 5 | int a[N]; 6 | 7 | int cal(int l, int r, int x) 8 | { 9 | if (a[r] < x) { 10 | return -1; 11 | } 12 | int res = 0; 13 | while (l <= r) { 14 | int mid = (l + r) >> 1; 15 | if (a[mid] >= x) { 16 | r = mid - 1; 17 | res = mid; 18 | } else { 19 | l = mid + 1; 20 | } 21 | } 22 | return a[res]; 23 | } 24 | 25 | int main() 26 | { 27 | int n; 28 | int m; 29 | scanf("%d %d", &n, &m); 30 | for (int i = 0; i < n; i++) { 31 | scanf("%d", &a[i]); 32 | } 33 | sort(a, a + n); 34 | while (m--) { 35 | int x; 36 | scanf("%d", &x); 37 | printf("%d\n", cal(0, n - 1, x)); 38 | } 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /基础算法/二分/binary_search_3.cc: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int N = 1e5 + 9; 4 | int a[N]; 5 | 6 | int cal(int l, int r, int x) 7 | { 8 | if (a[r] <= x) { 9 | return -1; 10 | } 11 | int res = 0; 12 | while (l <= r) { 13 | int mid = (l + r) >> 1; 14 | if (a[mid] > x) { 15 | r = mid - 1; 16 | res = mid; 17 | } else { 18 | l = mid + 1; 19 | } 20 | } 21 | return a[res]; 22 | } 23 | 24 | int main() 25 | { 26 | int n; 27 | int m; 28 | scanf("%d %d", &n, &m); 29 | for (int i = 0; i < n; i++) { 30 | scanf("%d", &a[i]); 31 | } 32 | sort(a, a + n); 33 | while (m--) { 34 | int x; 35 | scanf("%d", &x); 36 | printf("%d\n", cal(0, n - 1, x)); 37 | } 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /基础算法/二分/binary_search_4.cc: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int N = 1e5 + 9; 4 | int a[N]; 5 | 6 | int ok(int l, int r, int x) 7 | { 8 | while (l <= r) { 9 | int mid = (l + r) >> 1; 10 | if (a[mid] == x) { 11 | return 1; 12 | } 13 | if (a[mid] > x) { 14 | r = mid - 1; 15 | } else { 16 | l = mid + 1; 17 | } 18 | } 19 | return 0; 20 | } 21 | 22 | int calL(int l, int r, int x) 23 | { 24 | int res = 0; 25 | while (l <= r) { 26 | int mid = (l + r) >> 1; 27 | if (a[mid] >= x) { 28 | r = mid - 1; 29 | res = mid; 30 | } else { 31 | l = mid + 1; 32 | } 33 | } 34 | return res; 35 | } 36 | int calR(int l, int r, int x) 37 | { 38 | if (a[r] <= x) { 39 | return r + 1; 40 | } 41 | int res = 0; 42 | while (l <= r) { 43 | int mid = (l + r) >> 1; 44 | if (a[mid] > x) { 45 | r = mid - 1; 46 | res = mid; 47 | } else { 48 | l = mid + 1; 49 | } 50 | } 51 | return res; 52 | } 53 | 54 | int main() 55 | { 56 | int n; 57 | int m; 58 | scanf("%d %d", &n, &m); 59 | for (int i = 0; i < n; i++) { 60 | scanf("%d", &a[i]); 61 | } 62 | sort(a, a + n); 63 | while (m--) { 64 | int x; 65 | scanf("%d", &x); 66 | if (!ok(0, n - 1, x)) { 67 | puts("0"); 68 | } else { 69 | printf("%d\n", calR(0, n - 1, x) - calL(0, n - 1, x)); 70 | } 71 | } 72 | return 0; 73 | } 74 | -------------------------------------------------------------------------------- /基础算法/二分/binary_search_5.cc: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int N = 1e5 + 9; 4 | int a[N]; 5 | 6 | int cal(int l, int r, int x) 7 | { 8 | if (a[l] > x) { 9 | return -1; 10 | } 11 | int res = 0; 12 | while (l <= r) { 13 | int mid = (l + r) >> 1; 14 | if (a[mid] > x) { 15 | r = mid - 1; 16 | } else { 17 | l = mid + 1; 18 | res = mid; 19 | } 20 | } 21 | return a[res]; 22 | } 23 | 24 | int main() 25 | { 26 | int n; 27 | int m; 28 | scanf("%d %d", &n, &m); 29 | for (int i = 0; i < n; i++) { 30 | scanf("%d", &a[i]); 31 | } 32 | sort(a, a + n); 33 | while (m--) { 34 | int x; 35 | scanf("%d", &x); 36 | printf("%d\n", cal(0, n - 1, x)); 37 | } 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /基础算法/二分/binary_search_6.cc: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int N = 1e5 + 9; 4 | int a[N]; 5 | 6 | int cal(int l, int r, int x) 7 | { 8 | if (a[l] >= x) { 9 | return -1; 10 | } 11 | int res = 0; 12 | while (l <= r) { 13 | int mid = (l + r) >> 1; 14 | if (a[mid] >= x) { 15 | r = mid - 1; 16 | } else { 17 | l = mid + 1; 18 | res = mid; 19 | } 20 | } 21 | return a[res]; 22 | } 23 | 24 | int main() 25 | { 26 | int n; 27 | int m; 28 | scanf("%d %d", &n, &m); 29 | for (int i = 0; i < n; i++) { 30 | scanf("%d", &a[i]); 31 | } 32 | sort(a, a + n); 33 | while (m--) { 34 | int x; 35 | scanf("%d", &x); 36 | printf("%d\n", cal(0, n - 1, x)); 37 | } 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /数据结构/LCA/lac.cc: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int N = 1e6 + 9; 4 | const int M = 22; 5 | 6 | struct edge { 7 | int v, w, next; 8 | } e[N]; 9 | int p[N], eid; 10 | void init() 11 | { 12 | memset(p, -1, sizeof p); 13 | eid = 0; 14 | } 15 | void add(int u, int v, int w) 16 | { 17 | e[eid].v = v; 18 | e[eid].w = w; 19 | e[eid].next = p[u]; 20 | p[u] = eid++; 21 | } 22 | 23 | int h[N], dis[N], f[N][M + 3]; 24 | 25 | int lca(int x, int y) 26 | { 27 | if (h[x] < h[y]) { 28 | swap(x, y); 29 | } 30 | for (int i = M; i >= 0; i--) { 31 | if (h[f[x][i]] >= h[y]) { 32 | x = f[x][i]; 33 | } 34 | } 35 | if (x == y) { 36 | return x; 37 | } 38 | for (int i = M; i >= 0; i--) { 39 | if (f[x][i] != f[y][i]) { 40 | x = f[x][i]; 41 | y = f[y][i]; 42 | } 43 | } 44 | return f[x][0]; 45 | } 46 | 47 | void dfs(int u, int pre) 48 | { 49 | h[u] = h[pre] + 1; 50 | for (int i = 0; i <= M; i++) { 51 | f[u][i + 1] = f[f[u][i]][i]; 52 | } 53 | for (int i = p[u]; ~i; i = e[i].next) { 54 | int v = e[i].v; 55 | if (v != pre) { 56 | f[v][0] = u; 57 | dis[v] = dis[u] + e[i].w; 58 | dfs(v, u); 59 | } 60 | } 61 | } 62 | 63 | int main() 64 | { 65 | init(); 66 | int n, m; 67 | cin >> n; 68 | for (int i = 1; i < n; i++) { 69 | int x, y; 70 | cin >> x >> y; 71 | add(x, y, 1); 72 | add(y, x, 1); 73 | } 74 | dfs(1, 0); 75 | cin >> m; 76 | while (m--) { 77 | int x, y; 78 | cin >> x >> y; 79 | cout << dis[x] + dis[y] - 2 * dis[lca(x, y)] << endl; 80 | } 81 | return 0; 82 | } 83 | -------------------------------------------------------------------------------- /数据结构/RMQ/rmq.cc: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int N = 2e6 + 9; 4 | const int M = 22; 5 | 6 | int lg[M], a[N], f[N][M]; 7 | 8 | int main() 9 | { 10 | int n, m; 11 | cin >> n >> m; 12 | for (int i = 1; i <= n; i++) { 13 | cin >> a[i]; 14 | } 15 | lg[0] = -1; 16 | for (int i = 1; i <= n; i++) { 17 | lg[i] = lg[i >> 1] + 1; 18 | f[i][0] = a[i]; 19 | } 20 | for (int j = 1; j < M; j++) { 21 | for (int i = 1; i + (1 << j) - 1 <= n; i++) { 22 | f[i][j] = min(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]); 23 | } 24 | } 25 | for (int i = 1; i <= n; i++) { 26 | int x = max(1, i - m); 27 | int y = i - 1; 28 | if (y <= 0) { 29 | cout << 0 << endl; 30 | continue; 31 | } 32 | int s = lg[y - x + 1]; 33 | cout << min(f[x][s], f[y - (1 << s) + 1][s]) << endl; 34 | } 35 | return 0; 36 | } 37 | 38 | // https://www.luogu.com.cn/problem/P1440 39 | -------------------------------------------------------------------------------- /数据结构/sort/README.md: -------------------------------------------------------------------------------- 1 | # 常见的排序算法 2 | 3 | [题目链接](http://acm.hdu.edu.cn/showproblem.php?pid=1040) 4 | 5 | - 冒泡排序 6 | - 选择排序 7 | - 插入排序 8 | - 快速排 9 | - 归并排序 10 | - 堆排序 11 | - 桶排序 12 | - 基数排序 13 | - 希尔排序 14 | 15 | -------------------------------------------------------------------------------- /数据结构/sort/heap.cc: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | const int N = 1e3 + 9; 5 | int A[N], len; 6 | 7 | void push(int val) 8 | { 9 | A[++len] = val; 10 | 11 | int p = len; 12 | while (p > 1 && A[p / 2] > A[p]) { 13 | swap(A[p / 2], A[p]); 14 | p /= 2; 15 | } 16 | } 17 | 18 | int pop() 19 | { 20 | int res = A[1]; 21 | A[1] = A[len--]; 22 | 23 | int p = 1, t; 24 | while (p * 2 <= len) { 25 | if (p * 2 + 1 > len || A[p * 2] <= A[p * 2 + 1]) { 26 | t = p * 2; 27 | } else { 28 | t = p * 2 + 1; 29 | } 30 | if (A[p] > A[t]) { 31 | swap(A[p], A[t]); 32 | p = t; 33 | } else { 34 | break; 35 | } 36 | } 37 | return res; 38 | } 39 | 40 | int main() 41 | { 42 | int t; 43 | cin >> t; 44 | while (t--) { 45 | int n; 46 | cin >> n; 47 | for (int i = 0; i < n; i++) { 48 | int x; 49 | cin >> x; 50 | push(x); 51 | } 52 | while (n--) { 53 | cout << pop() << (n == 0 ? '\n' : ' '); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /数据结构/sort/maopao.cc: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | const int N = 1e3 + 9; 5 | int a[N]; 6 | 7 | void sort(int n) 8 | { 9 | for (int i = 0; i < n; i++) { 10 | for (int j = 0; j < n - i - 1; j++) { 11 | if (a[j] > a[j + 1]) { 12 | swap(a[j], a[j + 1]); 13 | } 14 | } 15 | } 16 | } 17 | 18 | int main() 19 | { 20 | int t; 21 | cin >> t; 22 | while (t--) { 23 | int n; 24 | cin >> n; 25 | for (int i = 0; i < n; i++) { 26 | cin >> a[i]; 27 | } 28 | sort(n); 29 | for (int i = 0; i < n; i++) { 30 | cout << a[i] << (i == n - 1 ? '\n' : ' '); 31 | } 32 | } 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /数据结构/sort/merge.cc: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int a[1010], f[1010]; 5 | 6 | void merge(int l, int m, int r) 7 | { 8 | int i = l, j = m + 1, k = 0; 9 | int n = r; 10 | while (i <= m || j <= n) { 11 | if (j > n || (i <= m && a[i] <= a[j])) { 12 | f[k++] = a[i++]; 13 | } else { 14 | f[k++] = a[j++]; 15 | } 16 | } 17 | for (int i = 0; i < k; i++) { 18 | a[l + i] = f[i]; 19 | } 20 | } 21 | 22 | void sort(int l, int r) 23 | { 24 | if (l < r) { 25 | int m = l + r >> 1; 26 | sort(l, m); 27 | sort(m + 1, r); 28 | merge(l, m, r); 29 | } 30 | } 31 | 32 | int main() 33 | { 34 | int t; 35 | cin >> t; 36 | while (t--) { 37 | int n; 38 | cin >> n; 39 | for (int i = 0; i < n; i++) { 40 | cin >> a[i]; 41 | } 42 | sort(0, n - 1); 43 | for (int i = 0; i < n; i++) { 44 | cout << a[i] << (i == n - 1 ? '\n' : ' '); 45 | } 46 | } 47 | return 0; 48 | } 49 | -------------------------------------------------------------------------------- /数据结构/sort/sort.cc: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int a[1010]; 5 | 6 | void qs(int s, int e) 7 | { 8 | if (s >= e) { 9 | return; 10 | } 11 | int l = s, r = e; 12 | int x = a[s]; 13 | while (l < r) { 14 | while (l < r && a[r] >= x) { 15 | r--; 16 | } 17 | a[l] = a[r]; 18 | while (l < r && a[l] <= x) { 19 | l++; 20 | } 21 | a[r] = a[l]; 22 | } 23 | a[r] = x; 24 | qs(s, r - 1); 25 | qs(r + 1, e); 26 | } 27 | 28 | int main() 29 | { 30 | int t; 31 | cin >> t; 32 | while (t--) { 33 | int n; 34 | cin >> n; 35 | for (int i = 0; i < n; i++) { 36 | cin >> a[i]; 37 | } 38 | qs(0, n - 1); 39 | for (int i = 0; i < n; i++) { 40 | cout << a[i] << (i == n - 1 ? '\n' : ' '); 41 | } 42 | } 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /数据结构/并查集/README.md: -------------------------------------------------------------------------------- 1 | # 并查集 2 | 3 | [题目链接](http://acm.hdu.edu.cn/showproblem.php?pid=1232) 4 | 5 | https://blog.csdn.net/xerxessimon/article/details/60151731 6 | 7 | 种类并查集 8 | 带权并查集 9 | 逆向并查集 10 | 11 | 12 | -------------------------------------------------------------------------------- /数据结构/并查集/union.cc: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | 4 | int n, m; 5 | int fa[1010]; 6 | 7 | int finds(int x) 8 | { 9 | if (fa[x] != x) { 10 | fa[x] = finds(fa[x]); 11 | } 12 | return fa[x]; 13 | } 14 | 15 | void merge(int x, int y) 16 | { 17 | int fx = finds(x); 18 | int fy = finds(y); 19 | if (fx != fy) { 20 | fa[fx] = fy; 21 | } 22 | } 23 | 24 | int main() 25 | { 26 | while (cin >> n >> m && n) { 27 | for (int i = 1; i <= n; i++) { 28 | fa[i] = i; 29 | } 30 | while (m--) { 31 | int x, y; 32 | cin >> x >> y; 33 | merge(x, y); 34 | } 35 | int ans = 0; 36 | for (int i = 1; i <= n; i++) { 37 | if (fa[i] == i) { 38 | ans++; 39 | } 40 | } 41 | cout << ans - 1 << endl; 42 | } 43 | return 0; 44 | } 45 | -------------------------------------------------------------------------------- /数据结构/树状数组/a.cc: -------------------------------------------------------------------------------- 1 | #include 2 | using namespace std; 3 | const int N = 5e4 + 9; 4 | int c[N]; 5 | 6 | void add(int x, int val) { 7 | while (x < N) { 8 | c[x] += num; 9 | x += x & -x; 10 | } 11 | } 12 | 13 | int sum(int x) { 14 | int res = 0; 15 | while (x) { 16 | res += c[x]; 17 | x -= x & -x; 18 | } 19 | return res; 20 | } 21 | 22 | int main() { 23 | int t; 24 | int n; 25 | int x; 26 | int y; 27 | string s; 28 | cin >> t; 29 | for (int tot = 1; tot <= t; tot++) { 30 | cout << "Case " << tot << ":" << endl; 31 | memset(a, 0, sizeof a); 32 | memset(c, 0, sizeof c); 33 | cin >> n; 34 | for (int i = 0; i <= n; i++) { 35 | cin >> x; 36 | add(i + 1, x); 37 | } 38 | while (cin >> s, s[0] != 'E') { 39 | cin >> x >> y; 40 | if (s[0] == 'Q') { 41 | cout << sum(y) - sum(x - 1) << endl; 42 | } else if (s[0] == 'A') { 43 | add(x, y); 44 | } else if (s[0] == 'S') { 45 | add(x, -y); 46 | } 47 | } 48 | } 49 | return 0; 50 | } 51 | // https://vjudge.net/problem/HDU-1166 52 | // https://www.cnblogs.com/xenny/p/9739600.html 53 | --------------------------------------------------------------------------------