Loading

算法总结

算法 algorithm

排序

Quick_Sort

void Quick_Sort(int q[], int l, int r) {
    if (l >= r) return;

    int i = l - 1, j = r + 1, x = q[(l + 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);
}

Merge_Sort

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 = 1, 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 (int i = l, j = 1; i <= r; i++, j++) q[i] = tmp[j];
}

二分查找

int search(int a[], int l, int r, int x) { // 查找大于等于x的第一个数字
	int ret = 0;
	while (l <= r) {
		int mid = (l + r) >> 1;
		if (a[mid] >= x) ret = mid, r = mid - ;
		else l = mid + 1;
	}
	return ret;
}

二分答案

// 区间[l, r]被划分成[l, mid - 1]和[mid, r]时使用
while (l < r) {
	int mid = (l + r + 1) >> 1;
	if (check(mid)) l = mid;
	else r = mid - 1;
}
// 区间[l, r]被划分成[l, mid]和[mid + 1, r]时使用
while (l < r) {
	int mid = (l + r) >> 1;
	if (check(mid)) r = mid;
	else l = mid + 1;
}

浮点数二分

double search(double l, double r)
{
    const double eps = 1e-6; // eps 表示精度,取决于题目对精度的要求
    while (r - l > eps)
    {
        double mid = (l + r) >> 1;
        if (check(mid)) r = mid;
        else l = mid;
    }
    return l;
}

三分

while (r - l > eps) {
  	mid = (lmid + rmid) / 2;
  	lmid = mid - eps;
  	rmid = mid + eps;
  	if (f(lmid) < f(rmid))
  	  r = mid;
 	else
  	  l = mid;
}

前缀和

一维前缀和

// 预处理
s[i] = a[1] + ... + a[i] = s[i-1] + a[i];
// 区间求和
a[l] + ... + a[r] = s[r] - s[l-1];

二维前缀和

// s[i][j] 表示第 i 行 j 列格子左上部分所有元素的和
s[i][j] = s[i-1][j] +s[i][j-1] - s[i-1][j-1] + a[i][j];
// 以(x1, y1)为左上角, (x2, y2)为右下角的子矩阵的和为:
ans = s[x2][y2] + s[x1 - 1][y1-1] - s[x1-1][y2] + s[x2][y1-1];

差分

前缀和的逆运算

一维差分

// 构造 b 数组, 使 a 数组为 b 数组的前缀和
a[l - r] + c -> b[l] += c

二维差分

a[x1][y1] - a[x2][y2] + c ->

b[x1][y1] += c, b[x1][y2+1] -= c, b[x2+1][y1] -= c, b[x2+1][y2+1] += c;

双指针

for (int i = 0, j = 0; i < n; i ++)
{
    while (j < i && check(i, j)) j++;
    // 具体问题的逻辑
}
//常见问题分类:
//   (1) 对于一个序列, 用两个指针维护一段区间
//   (2) 对于两个序列, 维护某种次序, 比如归并排序中合并两个有序序列的操作

位运算

/*
	n 在二进制表示中第 k 位是几
	先把第 k 位移到最后一位: n >> k;
	判断最后一位是几: n & 1
*/
n >> k & 1
// 返回 n 在二进制表示的最后一位 1
lowbit(n) = n & -n = n & (~n + 1)

离散化

特点 : 值域跨度大, 但稀疏

/*
	tips:
	a 中可能有重复元素, 需去重
	算出 x 离散化后的值, 二分
*/
vector<int> all; // 存储所有待离散化的值
sort(all.begin(), all.end()); // 排序
all.erase(unique(all.begin(), all.end()), all.end()); // 去重
int find(int x) { // 二分求 x 离散化后的值, 找到第一个大于等于 x 的位置
    int l = 0, r = all.size() - 1;
    while (l < r) {
        int mid = (l + r) >> 1;
        if (all[mid] >= x) r = mid;
        else l = mid + 1;
    }
    return r + 1; // 映射到[1, 2, ...n]
}

区间合并

将所有存在交集的区间合并

/*
	1. 按区间左端点排序
	2. 扫描合并
*/
void merge(vector <pair <int, int> > &se) {
    vector <pair <int, int> > res;
    sort(se.begin(), se.end());
    int st = -2e9, ed = -2e9;
    for (auto item : se)
        if (ed < item.first) {
            if (st != -2e9) res.push_back({st, ed});
            st = item.first, ed = item.second;
        }
        else ed = max(ed, item.second);
    if (st != -2e9) res.push_back({st, ed});
    se = res;
}

KMP

应用 解决字符串匹配问题

快速幂

int ksm(int x, int r) {
	int ret = 1;
	while (r) {
		if (r & 1) ret *= x;
		x *= x;
		r >> 1;
	}
	return ret;
}

矩阵快速幂

void add(LL &a, const &b) { // 取模
	a += b;
	a >= mid ? a -= mid : false;
}

void mul(LL A[N][N], LL B[N][N], LL C[N][N], int n, int s, int m) { // C = A * B;
	for (int i = 0; i < n; i++) 
		for (int j = 0; j <= m; j++) {
			C[i][j] = 0;
			for (int k = 0; k < s; k++)
				add(C[i][j], 1LL * A[i][k] * B[k][j] % mod);
		}
}

while (k) { // ans = a ^ k;
	if (k & 1LL) {
		mul(ans, a, tmp, n, n, n);
		memcpy(ans, tmp, sizeof(ans));
	}
	mul(a, a, tmp, n, n, n);
	memcpy(a, tmp, sizeof(a));
	k >> 1;
}

快读

inline int read() {
	int s = 0, w = 1; char ch = getchar();
	while (ch < '0' || ch >'9') {if (ch == '-') w = -1; ch = getchar();}
	while (ch >= '0' && ch <= '9') {s = (s << 3) + (s << 1) + ch - '0'; ch = getchar();}
	return s * w;
}
posted @ 2023-09-30 07:42  Gmor_cerr  阅读(54)  评论(0)    收藏  举报