//核心思想:分而治之 //函数参数:(需要处理的数组, 数组的左边界, 数组的右边界) //函数:使得左边小于x, 右边大于x voidquick_sort(int q[], int l, int r) { //递归出口 if (l >= r) return; //运用双指针,左指针指向的数小于x, 右指针指向的数大于x int x = (q[l] + q[r]) / 2; int i = l - 1, j = r + 1; while (i < j) { do i ++; while(q[i] < x); do j --; while(q[j] > x); if (i < j) swap(q[i], q[j]); } //递归处理左右子区间 quick_sort(q, l, j); quick_sort(q, j + 1, r); }
voidquick_sort(int q[], int l, int r) { if (l >= r) return; int x = (q[l] + q[r]) / 2; int i = l - 1, j = r + 1; while (i < j) { do i ++; while(q[i] < x); do j --; while(q[j] > x); if (i < j) swap(q[i], q[j]); } quick_sort(q, l, j); quick_sort(q, j + 1, r); } intmain() { int n; int q[N]; scanf("%d", &n); for (int i = 0; i < n; i ++ ) scanf("%d", &q[i]); quick_sort(q, 0, n - 1); for (int i = 0; i < n; i ++ ) printf("%d ", q[i]); }
voidquick_sort(int q[], int l, int r) { if (l >= r) return ; int x = (q[l] + q[r]) / 2; int i = l - 1, j = r + 1; while (i < j) { do i ++; while(q[i] < x); do j --; while(q[j] > x); if (i < j) swap(q[i], q[j]); } quick_sort(q, l, j); quick_sort(q, j + 1, r); } intmain() { int q[N]; int n, k; scanf ("%d %d", &n, &k); for (int i = 0; i < n; i ++ ) scanf("%d", &q[i]); quick_sort(q, 0, n - 1); printf("%d\n", q[k - 1]); }
voidmerge_sort(int q[], int l, int r) { //递归出口 if (l >= r) return ; //分成子问题 int mid = (l + r) / 2; merge_sort(q, l, mid); merge_sort(q, mid + 1, r); //合并 int i = l; int j = mid + 1; int k = 0; while (i <= mid && j <= r) { if (q[i] <= q[j]) tmp[k ++] = q[i ++]; else tmp[k ++] = q[j ++]; } while (i <= mid) tmp[k ++] = q[i ++]; while (j <= r) tmp[k ++] = q[j ++]; for (int i = 0, j = l; i < k; i ++, j ++) q[j] = tmp[i]; } intmain() { int q[N]; int n; scanf("%d", &n); for (int i = 0; i < n; i ++ ) scanf("%d", &q[i]); merge_sort(q, 0, n - 1); for (int i = 0; i < n; i ++ ) printf("%d ", q[i]); }
constint N = 100010; typedeflonglong LL; int q[N], tmp[N]; LL len; voidmerge_sort(int q[], int l, int r) { if (l >= r) return ; int mid = (l + r) / 2; merge_sort (q, l, mid); merge_sort (q, mid + 1, r); int i = l; int j = mid + 1; int k = 0; while (i <= mid && j <= r) { if (q[i] <= q[j]) tmp[k ++] = q[i ++]; else { tmp[k ++] = q[j ++]; len += mid - i + 1; } } while (i <= mid) tmp[k ++] = q[i ++]; while (j <= r) tmp[k ++] = q[j ++]; for (int i = 0, j = l; i < k; i ++, j ++ ) q[j] = tmp[i]; } intmain() { int n; scanf("%d", &n); for (int i = 0; i < n; i ++ ) scanf("%d", &q[i]); merge_sort(q, 0, n - 1); printf("%lld\n", len); }
二分查找
图解分析:
模板:
从左边开始找:
1 2 3 4 5 6 7 8
int l = 0; int r = n - 1; while (l < r) { int mid = (l + r) / 2; if (a[mid] >= x) r = mid; else l = mid + 1; }
从右边开始找:
1 2 3 4 5 6 7 8
l = 0; r = n - 1; while(l < r) { int mid = (l + r + 1) / 2; if (a[mid] <= x) l = mid; else r = mid - 1; }
大概思路:
根据a[mid]与x的大小关系,不断更新左右区间
当从右边开始找时,对于mid=(l+r+1)的说明:
当 l 和 r 相邻时(即 r = l + 1),使用 (l + r) / 2 计算得到的 mid 会等于 l(因为整数除法向下取整)。如果条件判断使得 l 更新为 mid,那么实际上 l 没有发生变化,导致 l 和 r 始终保持相邻状态,形成死循环。通过将 mid 的计算公式改为 (l + r + 1) / 2,可以确保 mid 等于 r,从而在下一次迭代中可以正确地更新 l 或 r,避免死循环。
intmain() { int n, q; scanf("%d%d", &n, &q); int a[N]; for (int i = 0; i < n; i ++ ) scanf("%d", &a[i]); while (q --) { int x; scanf("%d", &x); int l = 0; int r = n - 1; while (l < r) { int mid = (l + r) / 2; if (a[mid] >= x) r = mid; else l = mid + 1; } if (a[l] != x) printf("%d %d\n", -1, -1); else { printf("%d ", l); l = 0; r = n - 1; while(l < r) { int mid = (l + r + 1) / 2; if (a[mid] <= x) l = mid; else r = mid - 1; } printf("%d\n", r); } } }
intmain() { double x; scanf("%lf", &x); double l = -10000; double r = 10000; while (r - l >= 1e-8) { double mid = (l + r) / 2; if (mid * mid * mid >= x) r = mid; else l = mid; } printf("%.6lf\n", l); }
高精度运算
加法:
核心思想:
1.将数字当成字符串读入
2.字符串转换成数组(从低位向高位)
3.数组每个数字相加(注意有进位)
模板:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
vector<int> add(vector<int> x, vector<int> y) { vector<int> res; //存储加法结果 if (x.size() < y.size()) returnadd(y, x); int t = 0; for (int i = 0; i < x.size(); i ++ ) { t += x[i]; if (i < y.size()) t += y[i]; res.push_back(t % 10); t /= 10; } if (t) res.push_back(t); return res; }
vector<int> add(vector<int> x, vector<int> y) { vector<int> res; //存储加法结果 if (x.size() < y.size()) returnadd(y, x); int t = 0; for (int i = 0; i < x.size(); i ++ ) { t += x[i]; if (i < y.size()) t += y[i]; res.push_back(t % 10); t /= 10; } if (t) res.push_back(t); return res; } intmain() { vector<int> x, y; string a, b; cin >> a >> b; for (int i = a.size() - 1; i >= 0; i -- ) x.push_back(a[i] - '0'); for (int i = b.size() - 1; i >= 0; i -- ) y.push_back(b[i] - '0'); vector<int> res = add(x, y); for (int i = res.size() - 1; i >= 0; i -- ) cout << res[i]; }
char a[N], b[N]; int x[N], y[N]; int la, lb; int ans[N];
intadd(int x[], int y[]) { int t = 0; // 表示进位 for (int i = 0; i < la || i < lb; i ++) { int sum = x[i] + y[i] + t; // 当前加数之和 ans[i] = sum % 10; t = sum / 10; // 进位 } return t; } intmain() { scanf("%s%s", a, b); la = strlen(a); lb = strlen(b); for (int i = la - 1, t = 0; i >= 0; i --, t ++) x[t] = a[i] - '0'; for (int i = lb - 1, t = 0; i >= 0; i --, t ++) y[t] = b[i] - '0'; int t = add(x, y); // x + y if (t) printf("%d", t); int len = la > lb ? la : lb; for (int i = len - 1; i >= 0; i --) printf("%d", ans[i]); printf("\n"); return0; }
//比较x与y的大小 // x >= y 返回true boolcmp(vector<int> x, vector<int> y) { if (x.size() != y.size()) return x.size() > y.size(); for (int i = x.size() - 1; i >= 0; i -- ) if (x[i] != y[i]) return x[i] > y[i]; returntrue; } vector<int> sub(vector<int> x, vector<int> y) { vector<int> res; int t = 0; for (int i = 0; i < x.size(); i ++ ) { t = x[i] - t; if (i < y.size()) t -= y[i]; res.push_back((t + 10) % 10); if (t < 0) t = 1; else t = 0; } //前缀0去掉 while (res.size() > 1 && res.back() == 0) res.pop_back(); return res; }
//比较x与y的大小 // x >= y 返回true boolcmp(vector<int> x, vector<int> y) { if (x.size() != y.size()) return x.size() > y.size(); for (int i = x.size() - 1; i >= 0; i -- ) if (x[i] != y[i]) return x[i] > y[i]; returntrue; } vector<int> sub(vector<int> x, vector<int> y) { vector<int> res; int t = 0; for (int i = 0; i < x.size(); i ++ ) { t = x[i] - t; if (i < y.size()) t -= y[i]; res.push_back((t + 10) % 10); if (t < 0) t = 1; else t = 0; } //前缀0去掉 while (res.size() > 1 && res.back() == 0) res.pop_back(); return res; } intmain() { string a, b; cin >> a >> b; vector<int> x, y; for (int i = a.size() - 1; i >= 0; i -- ) x.push_back(a[i] - '0'); for (int i = b.size() - 1; i >= 0; i -- ) y.push_back(b[i] - '0'); vector<int> res; if (cmp(x, y)) res = sub(x, y); else { cout << '-'; res = sub(y, x); } for (int i = res.size() - 1; i >= 0; i -- ) cout << res[i]; return0; }
#include<stdio.h> #include<string.h> #include<math.h> #include<stdbool.h> #define N 100010
char a[N], b[N]; int x[N], y[N]; int la, lb; int ans[N];
intcmp(int x[], int y[]) { if (la > lb) return1; elseif (lb > la) return-1; else { for (int i = la - 1; i >= 0; i --) { if (x[i] > y[i]) return1; if (y[i] > x[i]) return-1; } return0; } } intremov(int x[], int y[]) { int t = 0; // 表示借位 for (int i = 0; i < la || i < lb; i ++) { x[i] -= t; if (x[i] < y[i]) t = 1; // 借一位 else t = 0; int sum = x[i] - y[i] + t * 10; ans[i] = sum % 10; } return t; } intmain() { scanf("%s%s", a, b); la = strlen(a); lb = strlen(b); for (int i = la - 1, t = 0; i >= 0; i --, t ++) x[t] = a[i] - '0'; for (int i = lb - 1, t = 0; i >= 0; i --, t ++) y[t] = b[i] - '0'; int t = cmp(x, y); if (t == 0) { printf ("0\n"); } elseif (t == 1) { remov(x, y); bool flag = true; for (int i = la - 1; i >= 0; i --) { if (ans[i] != 0) flag = false; if (flag) continue; elseprintf("%d", ans[i]); } } else { remov(y, x); bool flag = true; printf("-"); for (int i = lb - 1; i >= 0; i --) { if (ans[i] != 0) flag = false; if (flag) continue; elseprintf("%d", ans[i]); } } return0; }
乘法:
核心思想:
1.规模大的数字按照字符串读入
2.将字符串转化为数组
3.将数组中的每一个数与数字相乘
模版:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
vector<int> mul(vector<int> x, int y) { vector<int> res; int t = 0; for (int i = 0; i < x.size(); i ++ ) { t += x[i] * y; res.push_back(t % 10); t /= 10; } while (t) { res.push_back(t % 10); t /= 10; } return res; }
vector<int> mul(vector<int> x, int y) { vector<int> res; int t = 0; for (int i = 0; i < x.size(); i ++ ) { t += x[i] * y; res.push_back(t % 10); t /= 10; } while (t) { res.push_back(t % 10); t /= 10; } return res; } intmain() { string a; int b; cin >> a >> b; if (b == 0) { cout << '0'; return0; } vector<int> x; for (int i = a.size() - 1; i >= 0; i -- ) x.push_back(a[i] - '0'); vector<int> res = mul(x, b); for (int i = res.size() - 1; i >= 0; i -- ) cout << res[i]; return0; }
intfuc(int x[], int b) { int t = 0; //进位 for (int i = 0; i < l; i ++) { int sum = x[i] * b + t; ans[i] = sum % 10; t = sum / 10; } return t; } intmain() { scanf("%s%d", a, &b); l = strlen(a); for (int i = l - 1, t = 0; i >= 0; i --) x[t ++] = a[i] - '0'; if (b == 0 || (l == 1 && x[0] == 0)) { printf("0\n"); return0; } int t = fuc(x, b); if (t) printf("%d", t); for (int i = l - 1; i >= 0; i --) { printf("%d", ans[i]); } printf("\n"); return0; }
除法:
核心思想:
1.规模大的数字按照字符串读入
2.将字符串转化为数组
3.将数组中的每一个数与数字相除
4.去除前导0
模板:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
int t; vector<int> divide(vector<int> x, int b) { vector<int> res; for (int i = 0; i < x.size(); i ++ ) { t = t * 10 + x[i]; res.push_back(t / b); t = t % b; } reverse(res.begin(), res.end()); while (res.size() > 1 && res.back() == 0) res.pop_back(); return res; }
int t; vector<int> divide(vector<int> x, int b) { vector<int> res; for (int i = 0; i < x.size(); i ++ ) { t = t * 10 + x[i]; res.push_back(t / b); t = t % b; } reverse(res.begin(), res.end()); while (res.size() > 1 && res.back() == 0) res.pop_back(); return res; } intmain() { string a; int b; cin >> a >> b; vector<int> x; for (int i = a.size() - 1; i >= 0; i -- ) x.push_back(a[i] - '0'); reverse(x.begin(), x.end()); vector<int> res = divide(x, b); for (int i = res.size() - 1; i >= 0; i -- ) cout << res[i]; cout << endl; cout << t << endl; }
char a[N]; int x[N], b; int l; int ans[N]; int tmp[N];
boolcmp(int x[], int b) { int cnt = 0; int t = b; while (t) { tmp[cnt ++] = t % 10; t /= 10; } if (cnt > l) returntrue; elseif (cnt < l) returnfalse; else { for (int i = cnt - 1, j = 0; i >= 0; i --, j ++) { if (tmp[i] > x[j]) returntrue; elsereturnfalse; } } } intfuc(int x[], int b) { int t = 0; for (int i = 0; i < l; i ++) { int sum = x[i] + t * 10; ans[i] = sum / b; t = sum % b; } return t; } intmain() { scanf("%s%d", a, &b); l = strlen(a); for (int i = 0; i < l; i ++) x[i] = a[i] - '0'; int t = fuc(x, b); // b > a if (cmp(x, b)) printf("0\n"); else { int flag = true; for (int i = 0; i < l; i ++) { if (ans[i] != 0) flag = false; if (flag) continue; elseprintf("%d", ans[i]); } printf("\n"); } printf("%d\n", t); return0; }
前缀和与差分
一维前缀和:
图解分析:
模板:
1 2 3 4 5 6 7 8 9 10
int n, m; int sum[N]; voidPrefix_and(int a[]) { for (int i = 1; i <= n; i ++ ) sum[i] = sum[i - 1] + a[i]; } intSum(int l, int r) { return sum[r] - sum[l - 1]; }
int n, m; int sum[N]; voidPrefix_and(int a[]) { for (int i = 1; i <= n; i ++ ) sum[i] = sum[i - 1] + a[i]; } intSum(int l, int r) { return sum[r] - sum[l - 1]; } intmain() { cin >> n >> m; int a[N]; for (int i = 1; i <= n; i ++ ) scanf("%d", &a[i]); Prefix_and(a); while (m --) { int l, r; cin >> l >> r; cout << Sum(l, r) << endl;; } }
二维前缀和:
图解分析:
模板:
1 2 3 4 5 6 7 8 9 10 11 12 13
int n, m; int sum[N][N]; voidPrefix_and(int a[N][N]) { for (int i = 1; i <= n; i ++ ) for (int j = 1; j <= m; j ++ ) sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + a[i][j]; } intSum(int x1, int y1, int x2, int y2) { int res = sum[x2][y2] - sum[x2][y1 - 1] - sum[x1 - 1][y2] + sum[x1 - 1][y1 - 1]; return res; }
constint N = 100010; int a[N], b[N]; voidinsert(int l, int r, int c) { b[l] += c; b[r + 1] -= c; } intmain() { int n, m; cin >> n >> m; for (int i = 1; i <= n; i ++ ) cin >> a[i]; for (int i = 1; i <= n; i ++ ) insert(i, i, a[i]); while (m --) { int l, r, c; cin >> l >> r >> c; insert(l, r, c); } for (int i = 1 ; i <= n; i ++ ) { b[i] += b[i - 1]; cout << b[i] << ' '; } }
二维差分:
图解分析:
模板:
1 2 3 4 5 6 7 8
int a[N][N], b[N][N]; voidinsert(int x1, int y1, int x2, int y2, int c) { b[x1][y1] += c; b[x1][y2 + 1] -= c; b[x2 + 1][y1] -= c; b[x2 + 1][y2 + 1] += c; }
constint N = 1e5 + 10; int s[N]; intmain() { int n; scanf("%d", &n); int a[N]; for (int i = 0; i < n; i ++ ) scanf("%d", &a[i]); int res = 0; int j = 0; for (int i = 0; i < n; i ++ ) { s[a[i]] ++; while (s[a[i]] > 1) { s[a[j]] --; j ++; } res = max(res, i - j + 1); } cout << res << endl; }
intmain() { int n, m, x; cin >> n >> m >> x; LL a[N], b[N]; for (int i = 0; i < n; i ++ ) cin >> a[i]; for (int i = 0; i < m; i ++ ) cin >> b[i]; int j = m - 1; for (int i = 0; i < n; i ++ ) { while (j >= 0 && a[i] + b[j] > x) j --; if (a[i] + b[j] == x) cout << i << ' ' << j << endl; } }
intmain() { int n, m; cin >> n >> m; int a[N], b[N]; for (int i = 0; i < n; i ++ ) cin >> a[i]; for (int i = 0; i < m; i ++ ) cin >> b[i]; int i = 0, j = 0; while (i < n && j < m) { if (a[i] == b[j]) i ++; j ++; } if (i == n) puts("Yes"); elseputs("No"); }
vector<int> alls; intfind(int x) { int l = 0, r = alls.size(); while (l < r) { int mid = (l + r) / 2; if (alls[mid] >= x) r = mid; else l = mid + 1; } return l + 1; }