基础算法模板
基础算法
基础排序算法-快速排序
数据范围10510 ^ 5105, 算法时间复杂度O(nlogn)O(n\log n)O(nlogn)
#include <iostream>using namespace std;const int N = 1e5 + 10;
int n, w[N];void quick_sort(int l, int r) {if (l >= r) return;int val = w[l + r >> 1];int p1 = l - 1, p2 = r + 1;while (p1 < p2) {while (w[++p1] < val);while (w[--p2] > val);if (p1 < p2) swap(w[p1], w[p2]);}quick_sort(l, p2);quick_sort(p2 + 1, r);
}int main() {ios::sync_with_stdio(false);cin.tie(0);cin >> n;for (int i = 1; i <= n; ++i) cin >> w[i];quick_sort(1, n);for (int i = 1; i <= n; ++i) cout << w[i] << ' ';cout << '\n';return 0;
}
基础排序算法-第K个数
#include <iostream>using namespace std;const int N = 1e5 + 10;int n, k, w[N];void quick_sort(int l, int r) {if (l >= r) return;int val = w[l + r >> 1];int p1 = l - 1, p2 = r + 1;while (p1 < p2) {while (w[++p1] < val);while (w[--p2] > val);if (p1 < p2) swap(w[p1], w[p2]);}quick_sort(l, p2);quick_sort(p2 + 1, r);
}int main() {ios::sync_with_stdio(false);cin.tie(0);cin >> n >> k;for (int i = 1; i <= n; ++i) cin >> w[i];quick_sort(1, n);cout << w[k] << '\n';return 0;
}
基础排序算法-归并排序
先递归再合并, 简单的写法是自上而下的进行递归划分, 递归到最后一层, 开始合并, 向上递归最后完成排序, 算法时间复杂度O(nlogn)O(n \log n)O(nlogn), 空间相较于快速排序需要新增一个临时数组存储每次排序后的结果
#include <iostream>using namespace std;const int N = 1e5 + 10;int n, w[N], tmp[N];void merge_sort(int l, int r) {if (l >= r) return;int mid = l + r >> 1;merge_sort(l, mid), merge_sort(mid + 1, r);int p1 = l, p2 = mid + 1, k = 0;while (p1 <= mid && p2 <= r) {if (w[p1] <= w[p2]) tmp[k++] = w[p1++];else tmp[k++] = w[p2++];}while (p1 <= mid) tmp[k++] = w[p1++];while (p2 <= r) tmp[k++] = w[p2++];for (int i = l; i <= r; ++i) w[i] = tmp[i - l];
}int main() {ios::sync_with_stdio(false);cin.tie(0);cin >> n;for (int i = 0; i < n; ++i) cin >> w[i];merge_sort(0, n - 1);for (int i = 0; i < n; ++i) cout << w[i] << ' ';cout << '\n';return 0;
}
基础排序算法-归并排序求逆序对的数量
统计逆序对的算法核心是归并排序过程中自下而上的 合并有序的两段, 如果当前w[p1] > w[p2]
, 那么从mid + 1
到p2
与w[p1]
构成逆序对, 或者p1
到mid
与w[p2]
构成逆序对
#include <iostream>using namespace std;typedef long long LL;
const int N = 1e5 + 10;int n, w[N], tmp[N];
LL cnt = 0;void merge_sort(int l, int r) {if (l >= r) return;int mid = l + r >> 1;merge_sort(l, mid), merge_sort(mid + 1, r);int p1 = l, p2 = mid + 1, k = 0;while (p1 <= mid && p2 <= r) {if (w[p1] <= w[p2]) tmp[k++] = w[p1++];else {cnt += mid - p1 + 1;tmp[k++] = w[p2++];}}while (p1 <= mid) tmp[k++] = w[p1++];while (p2 <= r) tmp[k++] = w[p2++];for (int i = l; i <= r; ++i) w[i] = tmp[i - l];
}int main() {ios::sync_with_stdio(false);cin.tie(0);cin >> n;for (int i = 0; i < n; ++i) cin >> w[i];merge_sort(0, n - 1);cout << cnt << '\n';return 0;
}
基础二分算法-整数二分
对于含有相同数的一组有序序列查询左端点和右端点, 可以根据二分的原理进行查询小于等于val
的位置, 第一个大于等于val
的位置, 对应C++
语言当中就是lower_bound
和upper_bound
#include <iostream>using namespace std;const int N = 1e5 + 10, M = 1e4 + 10;int n, q;
int w[N];//找到右边界该位置左侧包括该位置都小于等于val
int find_right(int val) {int l = 0, r = n - 1;while (l < r) {int mid = l + r + 1 >> 1;if (w[mid] <= val) l = mid;else r = mid - 1;}return l;
}//找到左边界该位置包括该位置左侧都是小于等于val
int find_left(int val) {int l = 0, r = n - 1;while (l < r) {int mid = l + r >> 1;if (w[mid] >= val) r = mid;else l = mid + 1;}return r;
}int main() {ios::sync_with_stdio(false);cin.tie(0);cin >> n >> q;for (int i = 0; i < n; ++i) cin >> w[i];while (q--) {int val;cin >> val;int l = find_left(val), r = find_right(val);if (w[l] != val || w[r] != val) cout << -1 << ' ' << -1 << '\n';else cout << l << ' ' << r << '\n';}return 0;
}
基础二分算法-小数二分
#include <iostream>using namespace std;const double EPS = 1e-8;
double val;int main() {ios::sync_with_stdio(false);cin.tie(0);cin >> val;double l = -10010, r = 10000;while (abs(l - r) > EPS) {double mid = (l + r) / 2;if (mid * mid * mid <= val) l = mid;else r = mid;}printf("%.6lf\n", l);return 0;
}
高精度算法-高精度加法
#include <iostream>
#include <vector>using namespace std;vector<int> res;void calc_add(vector<int> &d1, vector<int> &d2) {if (d1.size() < d2.size()) {calc_add(d2, d1);return;}res.clear();int c = 0;for (int i = 0; i < d1.size(); ++i) {c += d1[i];if (i < d2.size()) c += d2[i];res.push_back(c % 10);c /= 10;}if (c) res.push_back(c);
}int main() {ios::sync_with_stdio(false);cin.tie(0);string s1, s2;vector<int> d1, d2;cin >> s1 >> s2;for (int i = s1.size() - 1; i >= 0; --i) d1.push_back(s1[i] - '0');for (int i = s2.size() - 1; i >= 0; --i) d2.push_back(s2[i] - '0');calc_add(d1, d2);for (int i = res.size() - 1; i >= 0; --i) cout << res[i];cout << '\n';return 0;
}
高精度算法-高精度减法
#include <iostream>
#include <vector>using namespace std;vector<int> res;void calc_add(vector<int> &d1, vector<int> &d2) {if (d1.size() < d2.size()) {calc_add(d2, d1);return;}res.clear();int c = 0;for (int i = 0; i < d1.size(); ++i) {c += d1[i];if (i < d2.size()) c += d2[i];res.push_back(c % 10);c /= 10;}if (c) res.push_back(c);
}bool cmp(vector<int> &d1, vector<int> &d2) {if (d1.size() != d2.size()) return d1.size() >= d2.size();for (int i = d1.size() - 1; i >= 0; --i) {if (d1[i] != d2[i]) return d1[i] >= d2[i];}return true;
}bool calc_sub(vector<int> &d1, vector<int> &d2) {if (!cmp(d1, d2)) {calc_sub(d2, d1);return false;}res.clear();int c = 0;for (int i = 0; i < d1.size(); ++i) {int val = d1[i] - c;if (i < d2.size()) val -= d2[i];if (val < 0) {val = (val + 10) % 10;c = 1;}else c = 0;res.push_back(val);}while (res.size() > 1 && res.back() == 0) res.pop_back();return true;
}int main() {ios::sync_with_stdio(false);cin.tie(0);string s1, s2;vector<int> d1, d2;cin >> s1 >> s2;for (int i = s1.size() - 1; i >= 0; --i) d1.push_back(s1[i] - '0');for (int i = s2.size() - 1; i >= 0; --i) d2.push_back(s2[i] - '0');if (!calc_sub(d1, d2)) cout << '-';for (int i = res.size() - 1; i >= 0; --i) cout << res[i];cout << '\n';return 0;
}
高精度算法-高精度乘法
高精度乘法一般用于一个高精度数字×正常大小的数字, 计算结果是高精度数字
#include <iostream>
#include <vector>using namespace std;vector<int> res;void calc_add(vector<int> &d1, vector<int> &d2) {if (d1.size() < d2.size()) {calc_add(d2, d1);return;}res.clear();int c = 0;for (int i = 0; i < d1.size(); ++i) {c += d1[i];if (i < d2.size()) c += d2[i];res.push_back(c % 10);c /= 10;}if (c) res.push_back(c);
}bool cmp(vector<int> &d1, vector<int> &d2) {if (d1.size() != d2.size()) return d1.size() >= d2.size();for (int i = d1.size() - 1; i >= 0; --i) {if (d1[i] != d2[i]) return d1[i] >= d2[i];}return true;
}bool calc_sub(vector<int> &d1, vector<int> &d2) {if (!cmp(d1, d2)) {calc_sub(d2, d1);return false;}res.clear();int c = 0;for (int i = 0; i < d1.size(); ++i) {int val = d1[i] - c;if (i < d2.size()) val -= d2[i];if (val < 0) {val = (val + 10) % 10;c = 1;}else c = 0;res.push_back(val);}while (res.size() > 1 && res.back() == 0) res.pop_back();return true;
}void calc_mul(vector<int> &d, int val) {res.clear();int c = 0;for (int i = 0; i < d.size(); ++i) {c += d[i] * val;res.push_back(c % 10);c /= 10;}if (c) res.push_back(c);while (res.size() > 1 && res.back() == 0) res.pop_back();
}int main() {ios::sync_with_stdio(false);cin.tie(0);vector<int> d1, d2;string s;int val;cin >> s >> val;for (int i = s.size() - 1; i >= 0; --i) d1.push_back(s[i] - '0');calc_mul(d1, val);for (int i = res.size() - 1; i >= 0; --i) cout << res[i];cout << '\n';return 0;
}
高精度算法-高精度除法
高精度除法一般是一个高精度数字除以一个正常int
数字, 计算结果一般是高精度数字和余数
#include <iostream>
#include <algorithm>
#include <vector>using namespace std;vector<int> res;void calc_add(vector<int> &d1, vector<int> &d2) {if (d1.size() < d2.size()) {calc_add(d2, d1);return;}res.clear();int c = 0;for (int i = 0; i < d1.size(); ++i) {c += d1[i];if (i < d2.size()) c += d2[i];res.push_back(c % 10);c /= 10;}if (c) res.push_back(c);
}bool cmp(vector<int> &d1, vector<int> &d2) {if (d1.size() != d2.size()) return d1.size() >= d2.size();for (int i = d1.size() - 1; i >= 0; --i) {if (d1[i] != d2[i]) return d1[i] >= d2[i];}return true;
}bool calc_sub(vector<int> &d1, vector<int> &d2) {if (!cmp(d1, d2)) {calc_sub(d2, d1);return false;}res.clear();int c = 0;for (int i = 0; i < d1.size(); ++i) {int val = d1[i] - c;if (i < d2.size()) val -= d2[i];if (val < 0) {val = (val + 10) % 10;c = 1;}else c = 0;res.push_back(val);}while (res.size() > 1 && res.back() == 0) res.pop_back();return true;
}void calc_mul(vector<int> &d, int val) {res.clear();int c = 0;for (int i = 0; i < d.size(); ++i) {c += d[i] * val;res.push_back(c % 10);c /= 10;}if (c) res.push_back(c);while (res.size() > 1 && res.back() == 0) res.pop_back();
}void calc_div(vector<int> &d, int val, int &r) {res.clear();r = 0;for (int i = d.size() - 1; i >= 0; --i) {r = r * 10 + d[i];res.push_back(r / val);r %= val;}reverse(res.begin(), res.end());while (res.size() > 1 && res.back() == 0) res.pop_back();
}int main() {ios::sync_with_stdio(false);cin.tie(0);vector<int> d1, d2;string s;int val;cin >> s >> val;for (int i = s.size() - 1; i >= 0; --i) d1.push_back(s[i] - '0');int r;calc_div(d1, val, r);for (int i = res.size() - 1; i >= 0; --i) cout << res[i];cout << '\n';cout << r << '\n';return 0;
}
高精度算法模板
#include <iostream>
#include <algorithm>
#include <vector>using namespace std;vector<int> res;void calc_add(vector<int> &d1, vector<int> &d2) {if (d1.size() < d2.size()) {calc_add(d2, d1);return;}res.clear();int c = 0;for (int i = 0; i < d1.size(); ++i) {c += d1[i];if (i < d2.size()) c += d2[i];res.push_back(c % 10);c /= 10;}if (c) res.push_back(c);
}bool cmp(vector<int> &d1, vector<int> &d2) {if (d1.size() != d2.size()) return d1.size() >= d2.size();for (int i = d1.size() - 1; i >= 0; --i) {if (d1[i] != d2[i]) return d1[i] >= d2[i];}return true;
}bool calc_sub(vector<int> &d1, vector<int> &d2) {if (!cmp(d1, d2)) {calc_sub(d2, d1);return false;}res.clear();int c = 0;for (int i = 0; i < d1.size(); ++i) {int val = d1[i] - c;if (i < d2.size()) val -= d2[i];if (val < 0) {val = (val + 10) % 10;c = 1;}else c = 0;res.push_back(val);}while (res.size() > 1 && res.back() == 0) res.pop_back();return true;
}void calc_mul(vector<int> &d, int val) {res.clear();int c = 0;for (int i = 0; i < d.size(); ++i) {c += d[i] * val;res.push_back(c % 10);c /= 10;}if (c) res.push_back(c);while (res.size() > 1 && res.back() == 0) res.pop_back();
}void calc_div(vector<int> &d, int val, int &r) {res.clear();r = 0;for (int i = d.size() - 1; i >= 0; --i) {r = r * 10 + d[i];res.push_back(r / val);r %= val;}reverse(res.begin(), res.end());while (res.size() > 1 && res.back() == 0) res.pop_back();
}