diff --git "a/\345\237\272\347\241\200\347\256\227\346\263\225" "b/\345\237\272\347\241\200\347\256\227\346\263\225" new file mode 100644 index 0000000000000000000000000000000000000000..619bb33f162b80bbbd97e7bb6dd47bc094195aa7 --- /dev/null +++ "b/\345\237\272\347\241\200\347\256\227\346\263\225" @@ -0,0 +1,1402 @@ +# 基础算法 + +[TOC] + +## 1.排序 + +### 1.1.快速排序 + +快速排序的基本思想来自于分治。 + +首先,确定分界点的方法: + +1. q[left]; +2. q[(left + right) / 2]; +3. q[right]; +4. 随机 + +第二步,则是调整区间,按照相应的要求,将数值划分为两部分。 + +第三步,递归处理左右两段数值。 + +使用两个指针分别指向左右两端,判断左右两端与指定的分界值x之间的关系,做出相应的调整。 + +**快速排序模板**: + +```c++ +#include +using namespace std; + +const int N = 1e6 + 10; + +int n; +int q[N]; + +void quick_sort(int q[], int l, int r) +{ + if(l >= r) return; + + int x = q[l], 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); +} + +int main() +{ + 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]); + } + return 0; +} +``` + +### 1.2.归并排序 + +也是通过分治的思想,将数组分成left和right + +1. + +```c++ +#include + +using namespace std; + +#define N 10000 +int n; +int q[N], tmp[N]; + +void merge_sort(int q[], int l, int r) +{ + if(l >= r) return; + int mid = l + r >> 1; + merge_sort(q, l, mid), merge_sort(q, mid + 1, r); + + int k = 0, i = l, j = mid + 1; + 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(i = l, j = 0;i <= r; i++, j++) + { + q[i] = tmp[j]; + } +} + +int main() +{ + 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]); + } + + return 0; +} +``` + +vector容器的模板 + +```c++ +void merge_sort(vector& arr, int left, int right) { + if (left < right) { + int mid = (left + right) / 2; + merge_sort(arr, left, mid); + merge_sort(arr, mid + 1, right); + merge(arr, left, mid, right); + } +} + +void merge(vector& arr, int left, int mid, int right) { + vector left_arr(arr.begin() + left, arr.begin() + mid + 1); + vector right_arr(arr.begin() + mid + 1, arr.begin() + right + 1); + int i = left - 1; + int j = mid; + int k = 0; + while (k < right - left + 1) { + if (j == right) { + arr[++i] = left_arr[++k]; + } else if (left_arr[++k] <= right_arr[j]) { + arr[++i] = left_arr[k]; + } else { + arr[++i] = right_arr[j]; + } + } +} +``` + +其中,`merge_sort`函数是递归函数,将待排序的数组分为左右两部分,再分别调用`merge_sort`函数进行排序。`merge`函数则是将左右两个已排序的数组合并成一个有序数组。 + +## 2.二分 + +通过某一条性质,每一次从中间进行分割,一半满足条件,一般不满足。不满足的那一部分就直接毙掉,满足的那一部分在调用二分法进行框定界限,从而使确定值越来越接近。 + +如果有单调性的话就一定可以二分,如果没有单调性也有可能可以二分 + +### 2.1.整数 + +前提是要排好序的,且必须要有解。 + +**整数二分法题目 - 数的范围**: + +```c++ +#include +using namespace std; + +const int N = 1e5 + 10; + +int n, m; +int q[N]; + +int main() +{ + scanf("%d%d", &n, &m); + for(int i = 0;i < n; i++) + { + scanf("%d", &q[i]); + } + + while(m--) + { + int x; + scanf("%d", &x); + + int l = 0,r = n - 1; + while(l < r) + { + int mid = l + r >> 2; + if(q[mid] >= x) r = mid; + else l = mid + 1; + } + + if(q[l] != x) cout << "-1 -1" << endl; + else + { + cout << l << ' '; + int l = 0, r = n - 1; + while(l < r) + { + int mid = l + r >> 1; + if(q[mid] <= x) l = mid; + else r = mid - 1; + } + + cout << l << endl; + } + } + + return 0; +} +``` + +### 2.2.浮点数 + +**开平方**: + +```c++ +#include +using namespace std; + +int main() +{ + double x; + scanf("%lf", &x); + + double l = 0, r = x; + while(r - l > 1e-8)//经验值,比要求小数多两位 + { + double mid = (l + r) / 2; + if(mid * mid >= x) r = mid; + else l = mid; + } + printf("%lf", l); + return 0; +} +``` + +## 3.高精度 + +### 3.1.高精度加法 + +两个正整数相加 + +```c++ +#include +#include +using namespace std; + +const int N = 1e6 + 10; + +vector add(vector &A, vector &B) +{ + vector C; + + int t = 0; + for(int i = 0;i < A.size() || i < B.size(); i++) + { + if(i < A.size()) t += A[i]; + if(i < B.size()) t += B[i]; + C.push_back(t%10); + t /= 10; + } + if(t) C.push_back(1); + return C; +} + +int main() +{ + string a, b; + vector A, B; + + cin >> a >> b;//a = '123456' + for(int i = a.size() - 1;i >= 0; i--) + { + A.push_back(a[i] - '0');//A = [6,5,4,3,2,1] + } + for(int i = b.size() - 1;i >= 0; i--) + { + B.push_back(b[i] - '0'); + } + + auto c = add(A, B); + + for(int i = c.size() - 1;i >= 0; i--) + { + printf("%d",c[i]); + } + return 0; +} +``` + +第1次回顾 + +```c++ +#include +#include +#include +#include + +using namespace std; + +const int N = 1000010; + +vector add(vector &A, vector &B) +{ + vector C; + + if(A.size() < B.size()) return add(B, A); + + int t = 0; + for(int i = 0;i < A.size() || i < B.size(); i++) + { + if(i < A.size()) t += A[i]; + if(i < B.size()) t += B[i]; + C.push_back(t % 10); + t /= 10; + } + + if(t) C.push_back(1); + + return C; +} + +int main() +{ + string a, b; + cin >> a >> b; + + vector A, B; + + for(int i = a.size() - 1;i >= 0; i--) + { + A.push_back(a[i] - '0'); + } + + for(int i = b.size() - 1;i >= 0; i--) + { + B.push_back(b[i] - '0'); + } + + auto C = add(A, B); + + for(int i = C.size() - 1;i >= 0; i--) + { + cout << C[i]; + } + + cout << endl; + + return 0; +} +``` + +第2次回顾: + +```c++ +#include +#include +#include +#include + +using namespace std; + +vector add(vector &A, vector &B) +{ + vector C; + + if(A.size() < B.size()) return add(B, A); + + int t = 0; + for(int i = 0;i < A.size() || i < B.size(); i++) + { + if(i < A.size()) t += A[i]; + if(i < B.size()) t += B[i]; + + C.push_back(t % 10); + t /= 10; + } + + if(t) C.push_back(1); + return C; +} + +int main() +{ + string a, b; + cin >> a >> b; + vector A, B; + + for(int i = a.size() - 1;i >= 0; i--) + A.push_back(a[i] - '0'); + + for(int i = b.size() - 1;i >= 0; i--) + B.push_back(b[i] - '0'); + + auto C = add(A, B); + + for(int i = C.size() - 1;i >= 0; i--) + cout << C[i]; + + cout << endl; + + return 0; +} +``` + + + +### 3.2.高精度减法 + +两个正整数相减。 + +首先要考虑到正负号,当小数减大数的时候,一定是负的; + +其次是一位不够,向上借位。 + +```c++ +#include +#include + +using namespace std; + +bool cmp(vector &A, vector &B) +{ + if(A.size() != B.size()) return A.size() > B.size(); + for(int i = A.size() - 1;i >= 0; i--) + { + if(A[i] != B[i]) return A[i] > B[i]; + } + return true; +} + +vector sub(vector &A, vector &B) +{ + vector C; + int t = 0; + for(int i = 0;i < A.size(); i++) + { + t = A[i] - t; + if(i < B.size()) t -= B[i]; + C.push_back((t + 10) % 10); + if(t < 0) t = 1; + else t = 0; + } + while(C.size() > 1 && C.back() == 0) + C.pop_back();//去掉前导0 + return C; +} + +int main() +{ + string a, b; + vector A, B; + + cin >> a >> b; + for(int i = a.size() - 1;i >= 0; i--) + { + A.push_back(a[i] - '0'); + } + for(int i = b.size() - 1;i >= 0; i--) + { + B.push_back(b[i] - '0'); + } + + if(cmp(A, B)) + { + auto c = sub(A, B); + for(int i = c.size() - 1;i >= 0; i--) + { + printf("%d",c[i]); + } + } + else + { + auto c = sub(B, A); + printf("-"); + for(int i = c.size() - 1;i >= 0; i--) + { + printf("%d",c[i]); + } + } + return 0; +} +``` + +第一次回顾: + +```c++ +#include +#include +#include +#include + +using namespace std; + +bool cmp(vector &A, vector &B) +{ + if(A.size() != B.size()) return A.size() > B.size(); + for(int i = A.size() - 1;i >= 0; i--) + { + if(A[i] != B[i]) return A[i] > B[i]; + } + return true; +} + +vector sub(vector &A, vector &B) +{ + vector C; + + int t = 0; + while(int i = 0;i < A.size(); i++) + { + t = A[i] - t; + if(i < B.size()) t -= B[i]; + + C.push_back((t + 10) % 10); + + if(t < 0) t = 1; + else t = 0; + } + + while(C.size() > 0 && C.back() == 0) C.pop_back(); + return C; +} + +int main() +{ + string a, b; + cin >> a >> b; + vector A, B; + + for(int i = a.size() - 1;i >= 0; i--) A.push_back(a[i] - '0'); + for(int i = b.size() - 1;i >= 0; i--) B.push_back(b[i] - '0'); + + if(cmp(A, B)) + { + auto C; + C = sub(A, B); + + for(int i = C.size();i >= 0; i--) + cout << C[i]; + + cout << endl; + } + else + { + cout << '-'; + auto C = sub(B, A); + + for(int i = C.size() - 1;i >= 0; i--) + cout << C[i]; + cout << endl; + } + + return 0; +} + +``` + + + +### 3.3.高精度乘法 + +两个正整数相乘,长整数乘上短整数的代码。 + +```c++ +#include +#include + +using namespace std; + +vector mul(vector&A, int b) +{ + vector C; + + int t = 0;//进位 + for(int i = 0;i < A.size() || t; i++) + { + if(i < A.size()) t += A[i] * b; + C.push_back(t % 10); + t /= 10; + } + return C; +} + +int main() +{ + string a; + int b; + cin >> a >> b; + vectorA; + + for(int i = a.size() - 1;i >= 0; i--) + { + A.push_back(a[i] - '0'); + } + + auto C = mul(A, b); + + for(int i = C.size() - 1;i >= 0; i--) + { + printf("%d",C[i]); + } + + return 0; +} +``` + +第1次回顾: + +```c++ +#include +#include +#include +#include + +using namespace std; + +vector mul(vector &A, int b) +{ + vector C; + + int t = 0; + for(int i = 0;i < A.size() || t; i++) + { + if(i < A.size()) t += A[i] * b; + C.push_back(t % 10); + t /= 10; + } + + return C; +} + +int main() +{ + string a; + int b; + cin >> a >> b; + + vector A; + for(int i = a.size() - 1;i >= 0; i--) A.push_back(a[i] - '0'); + + auto C = mul(A, b); + + for(int i = C.size() - 1;i >= 0; i--) + cout << C[i]; + cout << endl; + + return 0; +} +``` + + + +### 3.4.高精度除法 + +高精度的整数除以低精度的整数。 + +```c++ +#include +#include +#include +using namespace std; + +// A/b,商是C,余数是r +vector div(vector &A, int b, int &r) +{ + vector C;//商 + r = 0; + for(int i = A.size() - 1;i >= 0; i--) + { + r = r * 10 + A[i]; + C.push_back(r / b); + r %= b; + } + + reverse(C.begin(), C.end()); + while(C.size() >= 1 && C.back() == 0) C.pop_back(); + + return C; +} + +int main() +{ + string a; + int b; + cin >> a >> b; + + vector A; + for(int i = a.size() - 1;i >= 0; i--) + { + A.push_back(a[i] - '0'); + } + + int r; + auto C = div(A, b, r); + + for(int i = C.size() - 1;i >= 0; i--) + { + printf("%d",C[i]); + } + cout << endl << r << endl; + + return 0; +} +``` + +第一次回顾: + +```c++ +#include +#include +#include + +using namespace std; + +vector div(vector &A, int b, int &r) +{ + vector C; + + int r = 0; + for(int i = A.size();i >= 0; i--) + { + r = r * 10 + A[i]; + C.push_back(r / b); + r %= b; + } + + reverse(C.begin(), C.end()); + + return C; +} + +int main() +{ + string a; + int b; + + vector A; + for(int i = a.size() - 1;i >= 0; i--) cin >> a[i]; + + int r; + auto C = div(A, b, r); + + for(int i = a.size() - 1;i >= 0; i--) cout << C[i]; + cout << endl; + cout << r << endl; + + return 0; +} +``` + + + +## 4.前缀和 + +Si = a1 + a2 + a3 + ..... + an (注意:S0 = 0) + +如何求Si: + +```c++ +for(int i = 1;i <= n; i++) +{ + S[i] = S[i-1] + a[i]; +} +``` + +作用:[l, r] 时间复杂度O(n) + +用一次运算来计算任意段内的值:Sr - Sl-1 + +```c++ +#include +using namespace std; + +const int N = 100010; + +int n, m; +int a[N], s[N]; + +int main() +{ + ios::sync_with_stdio(false);//对cin的判断 + + scanf("%d%d",&n, &m); + for(int i = 1;i <= n; i++) + { + scanf("%d", &a[i]); + } + + for(int i = 1;i <= n; i++) + { + s[i] = s[i-1] + a[i]; + } + + while(m--) + { + int l, r; + scanf("%d%d", &l, &r); + printf("%d\n", s[r] - s[l-1]); + } + return 0; +} +``` + +图的面积裁剪问题 + +求和S[i] [j],这时候能用我们熟知的割补法来进行计算 + +```c++ +S[x2][y2] - S[x2][y1-1] - S[x1-1][y2] + S[x1- 1][y1 -1]; +``` + +这一块还是简单的,代码也是好写的 + +```c++ +#include +using namespace std; + +const int N = 1010; + +int n, m, q; +int a[N][N], s[N][N]; + +int main() +{ + scanf("%d%d%d", &n, &m, &q); + for(int i = 1;i <= n; i++) + { + for(int j = 1;j <= m; j++) + { + scanf("%d", &a[i][j]); + } + } + + for(int i = 1;i <= n; i++) + { + for(int j = 1;j <= m; j++) + { + s[i][j] = s[i-1][j] + s[i][j-1] - s[i-1][j-1] + a[i][j];//求前缀和 + } + } + + while(q--) + { + int x1, y1, x2, y2; + scanf("%d%d%d%d", &x1, &y1, &x2, &y2); + printf("%d", s[x2][y2] - s[x2][y1-1] - s[x1-1][y2] + s[x1-1][y1 -1]);//算部分矩阵和 + } + return 0; +} +``` + +## 5.差分 + +是前缀和的逆运算 + +a1, a2, .... an 构造b1, b2, ... , bn + +b1 =a1 b2 = a2 - a1 bn = an - an-1 + +a就是b的前缀和,b就是a的差分 + +**差分题目**: + +输入一段长度为n的整数序列 + +接下来输入m个操作,每个操作包含三个整数l,r,c,表示将序列中[l,r]之间的每个数加上c,输出进行完所有操作后的序列。 + +```c++ +#include +using namespace std; + +const int N = 100010; + +int n, m; +int a[N], b[N]; + +void insert(int l, int r, int c) +{ + b[l] += c; + b[r + 1] -= c; +} + +int main() +{ + scanf("%d%d", &n, &m); + for(int i = 1;i <= n; i++) + { + scanf("%d", &a[i]); + } + for(int i = 1;i <= n; i++) + { + insert(i, i, a[i]); + } + + while(m--) + { + int l,r,c; + scanf("%d%d%d", &l, &r, &c); + insert(l, r, c); + } + + for(int i = 1;i <= n; i++) + { + b[i] += b[i-1]; + } + + for(int i = 1;i <= n; i++) + { + printf("%d ", b[i]); + } + return 0; +} +``` + +我们上面的代码是一维的差分,接下来我们来构造一个差分矩阵。 + +```c++ +b[x1][y1] += c; +b[x2+1][y1] -= c; +b[x1][y2+1] -= c; +b[x2+1][y2+1] += c; +``` + +实现代码: + +```c++ +#include +using namespace std; + +const int N = 1010; + +int n, m, q; +int a[N][N], b[N][N]; + +void insert(int x1, int y1, int x2, int y2, int c) +{ + b[x1][y1] += c; + b[x2+1][y1] -= c; + b[x1][y2+1] -= c; + b[x2+1][y2+1] += c; +} + +int main() +{ + scanf("%d%d%d",&n, &m, &q); + + for(int i = 1;i <= n; i++) + { + for(int j = 1;j <= m; j++) + { + scanf("%d", &a[i][j]); + } + } + + for(int i = 1;i <= n; i++) + { + for(int j = 1;j <= m; j++) + { + insert(i, j, i, j, a[i][j]); + } + } + + while(q--) + { + int x1, x2, y1, y2, c; + scanf("%d%d%d%d%d",&x1, &y1, & x2, &y2, &c); + insert(x1, y1, x2, y2, c); + } + + for(int i = 1;i <= n; i++) + { + for(int j = 1;j <= m; j++) + { + b[i][j] += b[i-1][j] + b[i][j-1] -b[i-1][j-1]; + } + } + + for(int i = 1;i <= n; i++) + { + for(int j = 1;j <= m; j++) + { + printf("%d ",b[i][j]); + } + } + + return 0; +} +``` + +## 6.双指针算法 + +![img](../../../图片/u=3255471346,1636596706&fm=253&fmt=auto&app=138&f=JPEG) + +```c++ +for(int i = 0, j = 0;i < n; i++) +{ + while(j < i && check(i, j)) j++; + + //每道题目的具体思路 +} +``` + +**核心思想**: + +```c++ +for(int i = 0;i < n; i++) +{ + for(in j = 0;j < n; j++) +} +//算法复杂度O(n^2) +``` + +双指针算法能将上述的朴素算法优化到O(n) + +**输出字符串的每个单词**: + +前提每个单词间只有一个空格。 + +```c++ +#include +#include +using namespace std; + +int main() +{ + char str[1000]; + + gets(str); + + int n = strlen(str); + + for(int i = 0;i < n; i++) + { + int j = i; + while(j < n && str[j] != ' ') + { + j++; + } + + //本题的具体逻辑 + for(int k = i;k < j; k++) + cout << str[k]; + cout << endl; + + i = j; + } + return 0; +} +``` + +**最长连续不重复子序列**: + +给定一个长度为n的整数序列,请找出最长的不包含重复数字的连续序列,输出它的长度。 + +//朴素算法 + +```c++ +for(int i = 0;i < n; i++) +{ + for(int j = 0;j <= i; j++) + { + if(check(j, i)) + { + res = max(res, i - j + 1); + } + } +} +``` + +//双指针算法 + +```c++ +for(int i = 0, j = 0;i < n; i++) +{ + while(j <= i && check(j, i)) j++; + res = max(res, i - j + 1); +} +``` + +j:j往左最远能到的位置 + +**题目代码模板**: + +```c++ +#include + +using namespace std; + +const int N = 100010; + +int n; +int a[N], s[N]; + +int main() +{ + scanf("%d", &n); + for(int i = 0;i < n; i++) + { + scanf("%d", &a[i]); + } + + int res = 0; + for(int i = 0, j = 0;i < n; i++) + { + s[a[i]]++; + while(s[a[i]] > 1) + { + s[a[j]]--; + j++; + } + + res = max(res, i - j + 1); + } + + printf("%d\n", res); + + return 0; +} +``` + +## 7.位运算 + +**n的二进制表示第k位** + +1. 先把第k位数字移到最后一位 n >> k +2. 再观察个位的数字 x & 1 +3. lowbit(x):返回x的最后一位 x & -x = x & (~x + 1) + +```c++ +#include +using namespace std; + +int lowbit(int x) +{ + return x & -x; +} + +int main() +{ + int n; + cin >> n; + while(n--) + { + int x; + cin >> x; + + int res = 0; + while(x) x -= lowbit(x), res++;//每次减去x的最后一位 + + cout << res << ' '; + } + + return 0; +} +``` + +数据在内存中以2进制的形式存储 +对于整数来说: +整数二进制有3种表示形式:原码、反码、补码 +正整数:原码、反码、补码相同 +负整数:原码、反码、补码要进行计算的 +按照数据的数值直接写出的二进制序列就是原码 +原码的符号位不变,其他位按位取反,得到的就是反码 +反码+1,得到的就是补码 + +**存储举例1:** + +int a = -10; + +1000 0000 0000 0000 0000 0000 0000 1010 - 原码 + +1111 1111 1111 1111 1111 1111 1111 0101 - 反码 + +1111 1111 1111 1111 1111 1111 1111 1110 - 补码 + +FFFFFFF6-内存存储 + +内存存补码。 + +```c++ +#include +using namespace std; + +int lowbit(int x) +{ + return x & -x; +} + +int main() +{ + int n; + cin >> n; + while(n--) + { + int x; + cin >> x; + + int res = 0; + while(x) x -= lowbit(x), res++; + + cout << res << ' '; + } + return 0; +} +``` + +## 8.离散化 + +假设有一串极大的数据,我们对这串数据a[i]进行离散化,其中a[i]中可能会有重复的元素,首先就是处理去重的问题,然后再进行一一映射。 + +```c++ +vectoralls;//存储所有有待离散化的值 +sort(alls.begin(), alls.end());//将所有值排序 +alls.erase(unique(alls.begin(), alls.end()), alls.end());//去重 + +//二分法求出x对应的离散化的值 +int find(int x) +{ + int l = 0, r = alls.size() - 1; + while(l < r) + { + int mid = l + r >> 1; + if(alls[mid] >= x) r = mid; + else l = mid + 1; + } + return r + 1; +} +``` + +**例题:区间和** + +假设有一个无限长的数轴,数轴上的每个坐标上的数都是0。 + +现在,我们首先进行n次操作,每次操作将某一位置x上的数+c + +接下来,进行m次询问,每次询问包含两个整数l和r,你需要求出区间l和r之间所有数的和。 + +```c++ +#include +#include +#include + +using namespace std; + +typedef pair PII; + +const int N = 300010; + +int n, m; +int a[N], s[N]; + +vector alls; +vector add,query; + +int find(int x) +{ + int l = 0, r = alls.size() - 1; + while(l < r) + { + int mid = l + r >> 1; + if(alls[mid] >= x) r = mid; + else l = mid + 1; + } + return r + 1; +} + +int main() +{ + cin >> n >> m; + for(int i = 0;i < n; i++) + { + int x, c; + cin >> x >> c; + add.push_back({x, c}); + + alls.push_back(x); + } + + for(int i = 0;i < m; i++) + { + int l, r; + cin >> l >> r; + query.push_back({l, r}); + + alls.push_back(l); + alls.push_back(r); + } + + //去重 + sort(alls.begin(), alls.end()); + alls.erase(unique(alls.begin(), alls.end()), alls.end()); + + for(auto item:add) + { + int x = find(item.first); + a[x] += item.second; + } + + //预处理前缀和 + for(int i = 1;i <= alls.size(); i++) + { + s[i] = s[i - 1] + a[i]; + } + + //处理询问 + for(auto item:query) + { + int l = find(item.first), r = find(item.second); + cout << s[r] - s[l-1] << endl; + } + + return 0; +} +``` + +### 8.1.unique函数实现 + +```c++ +vector::iterator unique(vector &a) +{ + int j = 0; + for(int i = 0;i < a.size(); i++) + { + if(!a || a[i] != a[i - 1]) + a[j++] = a[i]; + } + //a[0]~a[j-1]所有的数都是不同的 + return a.begin() + j; +} +``` + +排完序的内容中,数要么就是第一个,要么就是a[i] ≠a[i - 1],Java和python方向是没有unique函数的,如果要写的话,就是做一个这样的迭代器。 + +## 9.区间合并 + +假设有大量区间,有的区间之间有重叠的部分,我们要将有交集的区间进行合并。 + +1. 按区间左端点排序 +2. 扫描整个区间,将所有可能有交点的区间进行合并 + +```c++ +#include +#include +#include + +using namespace std; + +typedef pair PII; + +const int N = 100010; + +int n; +vector segs; + +void merge(vector &segs) +{ + vector res; + + sort(segs.begin(), segs.end()); + + int st = -2e9, ed = -2e9; + for(auto seg : segs) + { + if(ed < seg.first) + { + if(st != - 2e9) res.push_back({st, ed}); + st = seg.first, ed = seg.second; + } + else ed = max(ed, seg.second); + } + + if(st != -2e9) res.push_back({st, ed}); + + segs = res; +} + +int main() +{ + cin >> n; + + for(int i = 0;i < n; i++) + { + int l ,r; + cin >> l >> r; + segs.push_back({l,r}); + } + + merge(segs); + + cout << segs.size() << endl; + + return 0; +} +``` +