写点什么

来自北京大学 NOIP 金牌选手 yxc 的常用代码模板 1——基础算法

  • 2021 年 11 月 12 日
  • 本文字数:1566 字

    阅读完需:约 5 分钟

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;


【一线大厂Java面试题解析+后端开发学习笔记+最新架构讲解视频+实战项目源码讲义】
浏览器打开:qq.cn.hn/FTf 免费领取
复制代码


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];


}

3.整数二分算法模板

bool check(int x) {/* ... */} // 检查 x 是否满足某种性质


// 区间[l, r]被划分成[l, mid]和[mid + 1, r]时使用:


int bsearch_1(int l, int r)


{


while (l < r)


{


int mid = l + r >> 1;


if (check(mid)) r = mid; // check()判断 mid 是否满足性质


else l = mid + 1;


}


return l;


}


// 区间[l, r]被划分成[l, mid - 1]和[mid, r]时使用:


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;


}

4.浮点数二分算法模板

bool check(double x) {/* ... */} // 检查 x 是否满足某种性质


double bsearch_3(double l, double r)


{


const double eps = 1e-6; // eps 表示精度,取决于题目对精度的要求


while (r - l > eps)


{


double mid = (l + r) / 2;


if (check(mid)) r = mid;


else l = mid;


}


return l;


}

5.高精度加法

// C = A + B, A >= 0, B >= 0


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;


}

6.高精度减法

// C = A - B, 满足 A >= B, A >= 0, B >= 0


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;


}

7.高精度乘低精度

// C = A * b, A >= 0, b > 0


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;


}

8.高精度除以低精度

// A / b = C ... r, A >= 0, b > 0


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;


}

9.一维前缀和

S[i] = a[1] + a[2] + ... a[i]


a[l] + ... + a[r] = S[r] - S[l - 1]

10.二维前缀和

S[i, j] =ij格子左上部分所有元素的和


(x1, y1)为左上角,(x2, y2)为右下角的子矩阵的和为:


S[x2, y2] - S[x1 - 1, y2] - S[x2, y1 - 1] + S[x1 - 1, y1 - 1]

11.一维差分

给区间[l, r]中的每个数加上cB[l] += c,B[r + 1] -= c

12.二维差分

给以(x1, y1)为左上角,(x2, y2)为右下角的子矩阵中的所有元素加上 c:


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

13.位运算

n的第k位数字: n >> k & 1


返回 n 的最后一位1lowbit(n) = n & -n

14.双指针算法

for (int i = 0, j = 0; i < n; i ++ )


{


while (j < i && check(i, j)) j ++ ;


// 具体问题的逻辑


}


常见问题分类:


(1) 对于一个序列,用两个指针维护一段区间


(2) 对于两个序列,维护某种次序,比如归并排序中合并两个有序序列的操作

评论

发布
暂无评论
来自北京大学NOIP金牌选手yxc的常用代码模板1——基础算法