1. 快排模板
1.1 快速排序
- 算法思路:
- 确定枢轴元素x(通常取:q[l],q[r],q[(l+r)/2],随机)
- 调整区间,使得x左侧元素皆小于等于x,右侧元素皆大于等于x
- 递归处理左右两侧
void quick_sort(int q[], int l, int r)
{
if (l >= r) return;
int i = l - 1, j = r + 1, x = q[l];
while (i < j)
{
do i ++ ; while (q[i] < x);
do j -- ; while (q[j] > x);
if (i < j) swap(q[i], q[j]);
else break;
}
quick_sort(q, l, j);
quick_sort(q, j + 1, r);
}
1.2 快速选择
int quick_select(int l, int r, int k){
if (l >= r) return q[l];
int x = q[l], i = l - 1, j = r + 1;
while (i < j){
while(q[++ i] < x);
while(q[-- j] > x);
if (i < j) swap(q[i], q[j]);
}
int sl = j - l + 1;
if (k <= sl) return quick_sort(l, j, k);
return quick_sort(j+1, r, k - sl);
}
2. 归并模板
2.1 归并排序
- 算法思路:
- 确定分界点mid = (l+r)/2
- 递归方式,对mid左侧序列和右侧序列进行归并排序
- 归并左右两侧已经有序的数组
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];
}
2.2 逆序对
- 算法思路:
- 左半边内部的逆序对数量:merge_sort(L, mid)
- 右半边内部的逆序对数量:merge_sort(mid + 1, R)
- 横跨两边的逆序对数量:在归并时,i指针指向左侧序列,j指针指向右侧序列
- 当q[i] <= q[j] 时,跳过
- 当q[i] > q[j] 时,此时对于q[j]而言构成的逆序对数量为mid - i + 1
int mid = l + r >> 1;
LL res = merge_sort(l, mid) + merge_sort(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++];
res += mid - i + 1;
}
}
3. 二分模板
3.1 整数二分
bool check(int x) {}
int bsearch_1(int l, int r)
{
while (l < r)
{
int mid = l + r >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
return l;
}
int bsearch_2(int l, int r)
{
while (l < r)
{
int mid = l + r + 1 >> 1;
if (check(mid)) l = mid;
else r = mid - 1;
}
return l;
}
3.2 浮点数二分
bool check(double x) {}
double bsearch_3(double l, double r)
{
const double eps = 1e-6;
while (r - l > eps)
{
double mid = (l + r) / 2;
if (check(mid)) r = mid;
else l = mid;
}
return l;
}
4. 高精度
4.1 高精度加法
vector<int> add(vector<int> &A, vector<int> &B)
{
if (A.size() < B.size()) return add(B, A);
vector<int> C;
int t = 0;
for (int i = 0; i < A.size(); i ++ )
{
t += A[i];
if (i < B.size()) t += B[i];
C.push_back(t % 10);
t /= 10;
}
if (t) C.push_back(t);
return C;
}
4.2 高精度减法
vector<int> sub(vector<int> &A, vector<int> &B)
{
vector<int> C;
for (int i = 0, t = 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();
return C;
}
4.3 高精度乘低精度
vector<int> mul(vector<int> &A, int b)
{
vector<int> 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;
}
while (C.size() > 1 && C.back() == 0) C.pop_back();
return C;
}
4.4 高精度除低精度
vector<int> div(vector<int> &A, int b, int &r)
{
vector<int> 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;
}
5. 前缀和
5.1 一维前缀和
for (int i = 1; i <= n; i++){
S[i] = S[i-1] + a[i]
}
a[l] + ... + a[r] = S[r] - S[l - 1]
5.2 二维前缀和
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];
}
}
S[x2, y2] - S[x1 - 1, y2] - S[x2, y1 - 1] + S[x1 - 1, y1 - 1]
6. 差分
6.1 一维差分
B[l] += c, B[r + 1] -= c
void insert(int l, int r, int c){
b[l] += c;
b[r + 1] -= c;
}
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];
6.2 二维差分
S[x1, y1] += c;
S[x2 + 1, y1] -= c;
S[x1, y2 + 1] -= c;
S[x2 + 1, y2 + 1] += c;
void insert(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;
}
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, y1, x2, 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];
}
printf("\n");
}
7. note
ios::sync_with_stdio(false);