基础算法(二)学习笔记

举报
irrational 发表于 2022/01/18 01:26:15 2022/01/18
【摘要】 除法变成*10的减法  前缀和的小技巧 ios : : sync_with_stdio( false);l 消时 二维前缀和   二维差分 差分,O(·1·) 高精度乘法 #include <iostream>#include <vector&...

除法变成*10的减法

 前缀和的小技巧

ios : : sync_with_stdio( false);l


消时

二维前缀和

 

二维差分

差分,O(·1·)

高精度乘法


  
  1. #include <iostream>
  2. #include <vector>
  3. using namespace std;
  4. vector<int> mul(vector<int> &A, int b)
  5. {
  6. vector<int> C;
  7. int t = 0;
  8. for (int i = 0; i < A.size() || t; i ++ )
  9. {
  10. if (i < A.size()) t += A[i] * b;
  11. C.push_back(t % 10);
  12. t /= 10;
  13. }
  14. while (C.size() > 1 && C.back() == 0) C.pop_back();
  15. return C;
  16. }
  17. int main()
  18. {
  19. string a;
  20. int b;
  21. cin >> a >> b;
  22. vector<int> A;
  23. for (int i = a.size() - 1; i >= 0; i -- ) A.push_back(a[i] - '0');
  24. auto C = mul(A, b);
  25. for (int i = C.size() - 1; i >= 0; i -- ) printf("%d", C[i]);
  26. return 0;
  27. }

  
  1. //前缀和
  2. #include <iostream>
  3. using namespace std;
  4. const int N = 100010;
  5. int n, m;
  6. int a[N], s[N];
  7. int main()
  8. {
  9. scanf("%d%d", &n, &m);
  10. for (int i = 1; i <= n; i ++ ) scanf("%d", &a[i]);
  11. for (int i = 1; i <= n; i ++ ) s[i] = s[i - 1] + a[i]; // 前缀和的初始化
  12. while (m -- )
  13. {
  14. int l, r;
  15. scanf("%d%d", &l, &r);
  16. printf("%d\n", s[r] - s[l - 1]); // 区间和的计算
  17. }
  18. return 0;
  19. }

  
  1. //高精度除法
  2. #include <iostream>
  3. #include <vector>
  4. #include <algorithm>
  5. using namespace std;
  6. vector<int> div(vector<int> &A, int b, int &r)
  7. {
  8. vector<int> C;
  9. r = 0;
  10. for (int i = A.size() - 1; i >= 0; i -- )
  11. {
  12. r = r * 10 + A[i];
  13. C.push_back(r / b);
  14. r %= b;
  15. }
  16. reverse(C.begin(), C.end());
  17. while (C.size() > 1 && C.back() == 0) C.pop_back();
  18. return C;
  19. }
  20. int main()
  21. {
  22. string a;
  23. vector<int> A;
  24. int B;
  25. cin >> a >> B;
  26. for (int i = a.size() - 1; i >= 0; i -- ) A.push_back(a[i] - '0');
  27. int r;
  28. auto C = div(A, B, r);
  29. for (int i = C.size() - 1; i >= 0; i -- ) cout << C[i];
  30. cout << endl << r << endl;
  31. return 0;
  32. }

  
  1. //子矩阵的和
  2. #include <iostream>
  3. using namespace std;
  4. const int N = 1010;
  5. int n, m, q;
  6. int s[N][N];
  7. int main()
  8. {
  9. scanf("%d%d%d", &n, &m, &q);
  10. for (int i = 1; i <= n; i ++ )
  11. for (int j = 1; j <= m; j ++ )
  12. scanf("%d", &s[i][j]);
  13. for (int i = 1; i <= n; i ++ )
  14. for (int j = 1; j <= m; j ++ )
  15. s[i][j] += s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1];
  16. while (q -- )
  17. {
  18. int x1, y1, x2, y2;
  19. scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
  20. printf("%d\n", s[x2][y2] - s[x1 - 1][y2] - s[x2][y1 - 1] + s[x1 - 1][y1 - 1]);
  21. }
  22. return 0;
  23. }

  
  1. //差分
  2. #include <iostream>
  3. using namespace std;
  4. const int N = 100010;
  5. int n, m;
  6. int a[N], b[N];
  7. void insert(int l, int r, int c)
  8. {
  9. b[l] += c;
  10. b[r + 1] -= c;
  11. }
  12. int main()
  13. {
  14. scanf("%d%d", &n, &m);
  15. for (int i = 1; i <= n; i ++ ) scanf("%d", &a[i]);
  16. for (int i = 1; i <= n; i ++ ) insert(i, i, a[i]);
  17. while (m -- )
  18. {
  19. int l, r, c;
  20. scanf("%d%d%d", &l, &r, &c);
  21. insert(l, r, c);
  22. }
  23. for (int i = 1; i <= n; i ++ ) b[i] += b[i - 1];
  24. for (int i = 1; i <= n; i ++ ) printf("%d ", b[i]);
  25. return 0;
  26. }

  
  1. //差分矩阵
  2. #include <iostream>
  3. using namespace std;
  4. const int N = 1010;
  5. int n, m, q;
  6. int a[N][N], b[N][N];
  7. void insert(int x1, int y1, int x2, int y2, int c)
  8. {
  9. b[x1][y1] += c;
  10. b[x2 + 1][y1] -= c;
  11. b[x1][y2 + 1] -= c;
  12. b[x2 + 1][y2 + 1] += c;
  13. }
  14. int main()
  15. {
  16. scanf("%d%d%d", &n, &m, &q);
  17. for (int i = 1; i <= n; i ++ )
  18. for (int j = 1; j <= m; j ++ )
  19. scanf("%d", &a[i][j]);
  20. for (int i = 1; i <= n; i ++ )
  21. for (int j = 1; j <= m; j ++ )
  22. insert(i, j, i, j, a[i][j]);
  23. while (q -- )
  24. {
  25. int x1, y1, x2, y2, c;
  26. cin >> x1 >> y1 >> x2 >> y2 >> c;
  27. insert(x1, y1, x2, y2, c);
  28. }
  29. for (int i = 1; i <= n; i ++ )
  30. for (int j = 1; j <= m; j ++ )
  31. b[i][j] += b[i - 1][j] + b[i][j - 1] - b[i - 1][j - 1];
  32. for (int i = 1; i <= n; i ++ )
  33. {
  34. for (int j = 1; j <= m; j ++ ) printf("%d ", b[i][j]);
  35. puts("");
  36. }
  37. return 0;
  38. }

  
  1. //最长连续不重复子序列
  2. #include <iostream>
  3. using namespace std;
  4. const int N = 100010;
  5. int n;
  6. int q[N], s[N];
  7. int main()
  8. {
  9. scanf("%d", &n);
  10. for (int i = 0; i < n; i ++ ) scanf("%d", &q[i]);
  11. int res = 0;
  12. for (int i = 0, j = 0; i < n; i ++ )
  13. {
  14. s[q[i]] ++ ;
  15. while (j < i && s[q[i]] > 1) s[q[j ++ ]] -- ;
  16. res = max(res, i - j + 1);
  17. }
  18. cout << res << endl;
  19. return 0;
  20. }

  
  1. //数组元素的目标和
  2. #include <iostream>
  3. using namespace std;
  4. const int N = 1e5 + 10;
  5. int n, m, x;
  6. int a[N], b[N];
  7. int main()
  8. {
  9. scanf("%d%d%d", &n, &m, &x);
  10. for (int i = 0; i < n; i ++ ) scanf("%d", &a[i]);
  11. for (int i = 0; i < m; i ++ ) scanf("%d", &b[i]);
  12. for (int i = 0, j = m - 1; i < n; i ++ )
  13. {
  14. while (j >= 0 && a[i] + b[j] > x) j -- ;
  15. if (j >= 0 && a[i] + b[j] == x) cout << i << ' ' << j << endl;
  16. }
  17. return 0;
  18. }

  
  1. //二进制中1的个数
  2. #include <iostream>
  3. using namespace std;
  4. int main()
  5. {
  6. int n;
  7. scanf("%d", &n);
  8. while (n -- )
  9. {
  10. int x, s = 0;
  11. scanf("%d", &x);
  12. for (int i = x; i; i -= i & -i) s ++ ;
  13. printf("%d ", s);
  14. }
  15. return 0;
  16. }

  
  1. //区间和
  2. #include <iostream>
  3. #include <vector>
  4. #include <algorithm>
  5. using namespace std;
  6. typedef pair<int, int> PII;
  7. const int N = 300010;
  8. int n, m;
  9. int a[N], s[N];
  10. vector<int> alls;
  11. vector<PII> add, query;
  12. int find(int x)
  13. {
  14. int l = 0, r = alls.size() - 1;
  15. while (l < r)
  16. {
  17. int mid = l + r >> 1;
  18. if (alls[mid] >= x) r = mid;
  19. else l = mid + 1;
  20. }
  21. return r + 1;
  22. }
  23. vector<int>::iterator unique(vector<int> &a)
  24. {
  25. int j = 0;
  26. for (int i = 0; i < a.size(); i ++ )
  27. if (!i || a[i] != a[i - 1])
  28. a[j ++ ] = a[i];
  29. // a[0] ~ a[j - 1] 所有a中不重复的数
  30. return a.begin() + j;
  31. }
  32. int main()
  33. {
  34. cin >> n >> m;
  35. for (int i = 0; i < n; i ++ )
  36. {
  37. int x, c;
  38. cin >> x >> c;
  39. add.push_back({x, c});
  40. alls.push_back(x);
  41. }
  42. for (int i = 0; i < m; i ++ )
  43. {
  44. int l, r;
  45. cin >> l >> r;
  46. query.push_back({l, r});
  47. alls.push_back(l);
  48. alls.push_back(r);
  49. }
  50. // 去重
  51. sort(alls.begin(), alls.end());
  52. alls.erase(unique(alls), alls.end());
  53. // 处理插入
  54. for (auto item : add)
  55. {
  56. int x = find(item.first);
  57. a[x] += item.second;
  58. }
  59. // 预处理前缀和
  60. for (int i = 1; i <= alls.size(); i ++ ) s[i] = s[i - 1] + a[i];
  61. // 处理询问
  62. for (auto item : query)
  63. {
  64. int l = find(item.first), r = find(item.second);
  65. cout << s[r] - s[l - 1] << endl;
  66. }
  67. return 0;
  68. }

  
  1. #include <iostream>
  2. #include <vector>
  3. #include <algorithm>
  4. using namespace std;
  5. typedef pair<int, int> PII;
  6. void merge(vector<PII> &segs)
  7. {
  8. vector<PII> res;
  9. sort(segs.begin(), segs.end());
  10. int st = -2e9, ed = -2e9;
  11. for (auto seg : segs)
  12. if (ed < seg.first)
  13. {
  14. if (st != -2e9) res.push_back({st, ed});
  15. st = seg.first, ed = seg.second;
  16. }
  17. else ed = max(ed, seg.second);
  18. if (st != -2e9) res.push_back({st, ed});
  19. segs = res;
  20. }
  21. int main()
  22. {
  23. int n;
  24. scanf("%d", &n);
  25. vector<PII> segs;
  26. for (int i = 0; i < n; i ++ )
  27. {
  28. int l, r;
  29. scanf("%d%d", &l, &r);
  30. segs.push_back({l, r});
  31. }
  32. merge(segs);
  33. cout << segs.size() << endl;
  34. return 0;
  35. }

 

 

 

 

 

 

解题卡片:

1、二分法关键在于不陷入死循环,找到一个最适合点,对左右径行递归,同时避免死循环

2、快速排序关键与双指针有关,不断地减少逆序

3、归并排序除了快、稳定,而且还可以求逆序对:

        归并排序:
        1.[L,R]=> [L, mid], [mid + 1,R]

        2.递归排序[L, mid]和[mid + 1,R]

        3.归并,将左右两个有序序列合并成一个有序序列

具体而言,归并如何求出逆序对?

首先,归并是将数据不断的划分,直到最小,然后将最小的那部分不断地合并,而左边的没有用,先用的右边的那一块进行归并,那么就会产生逆序对!

总而言之,思考要往人类能够理解的方向上靠,否则还是会对身心造成伤害、、、

4、对于浮点数的二分法,也就是用牛顿法,二分法去做就好了

5、qi大于qj,那么qi后的数都与qj逆序(逆序对)

6、运行小程序,python和js都很快,因为不需要编译;而C++和java是需要编译的。

7、一维差分需要二重,二维差分需要四重,三维差分需要八重。

有问题可以留言探讨~~

文章来源: blog.csdn.net,作者:irrationality,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/weixin_54227557/article/details/120673238

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。