AcWing算法基础课笔记 1.基础算法
创始人
2024-02-24 21:54:53

目录

  • AcWing算法基础课笔记 1.基础算法
    • 二分排序
      • 基本思想
      • 代码
    • 归并排序
      • 基本思路
      • 代码
    • 高精度计算
      • 加法
      • 减法
      • 乘法
      • 除法
    • 前缀和
      • 一维
      • 二维

AcWing算法基础课笔记 1.基础算法

二分排序

基本思想

基于分治的思想

  1. 确定哨兵xxx:可以取左边界,中间值,右边界,甚至是任意值;
  2. 分区间:让小于xxx的值全都归到xxx的左边,大于xxx的值全都归到xxx的右边;
  3. 递归处理左右两端直到整个序列有序

代码

这是严蔚敏版数据结构快排的代码,也是我我一直用的代码,不是y神的模板。

去打洛谷题会报TLE

#include 
using namespace std;const int N = 100010;
int Array[N];//分区间
int partition(int* array, int low, int high){int value = array[low];while(low < high){while(low < high && array[high] >= value) high--;array[low] = array[high];while(low < high && array[low] <= value) low++;array[high] = array[low];}array[low] = value;return low;
}//递归处理
void quicksort(int* array, int low, int high){if(low < high){int newvalue = partition(array, low, high);quicksort(array, low, newvalue);quicksort(array, newvalue+1, high);}
}int main(){int n;cin >> n;for(int i = 0; i < n; i++) cin >> Array[i];quicksort(Array, 0, n-1);for(int i = 0; i < n; i++) cout << Array[i] << " ";return 0;
}

归并排序

基本思路

基于分治的思想

  1. 确定分界点 mid=(low+high)/2mid = (low + high) / 2mid=(low+high)/2
  2. 递归分解左右部分,直到不可再分
  3. 回溯归并

详细的思路讲解见归并排序详解:20分钟理解归并排序 ,讲的真的很好很好

代码

#include 
using namespace std;const int N = 100010;
int Array[N],tmp[N];void mergesort(int* array, int low, int high){if(low >= high) return;                   //数组没有元素或者只有一个元素时,直接返回int mid = (low + high) / 2;//递归分解左右部分,直到不可再分mergesort(array, low, mid);mergesort(array, mid + 1, high);int k = 0, i = low, j = mid + 1;//归并:合二为一while(i <= mid && j <= high){              //对每个分组进行排序if(array[i] <= array[j]) tmp[k++] = array[i++];else tmp[k++] = array[j++]; }//将剩下来的数组元素直接加到数组后面while(i <= mid) tmp[k++] = array[i++];while(j <= high) tmp[k++] = array[j++];for(int i = low, j = 0; i <= high; i++ , j++) array[i] = tmp[j];
}int main(){int n;cin >> n;for(int i = 0; i < n; i++) cin >> Array[i];mergesort(Array, 0, n-1);for(int i = 0; i < n; i++) cout << Array[i] << " ";return 0;
}

高精度计算

高精度计算即大整数的加减乘除,C++中没有表示大整数的类型,最长的long long也只有64位

而大整数指的是数字长度≤106\leq 10^6≤106,注意是长度,不是数值。而小整数指的是数值≤109\leq 10^9≤109

而在实际做题或者应用中,通常是这四种:

  • 两个大整数相加
  • 两个大整数相减
  • 一个大整数乘以一个小整数
  • 一个大整数除以一个小整数

大整数的存储:对于大整数通常用数组存储,从低位到高位存储比较方便。

加法

#include
#include
#includeusing namespace std;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];        //每一位A[i]+B[i]+tC.emplace_back(t % 10);            //存储的是模10的值t = t / 10;                        //重新计算进位用于下一位的计算}if(t) C.emplace_back(t);               //如果最后仍然有进位return C;
}int main(){string a,b;vector A,B;cin >> a >> b;for(int i = a.size() - 1; i >= 0; i--) A.emplace_back(a[i] - '0');for(int i = b.size() - 1; i >= 0; i--) B.emplace_back(b[i] - '0');vector C = add(A, B);for(int i = C.size() - 1; i >= 0; i--) cout << C[i];return 0;
}

减法

减法跟加法一样,需要额外考虑的是A与B谁大,并调用对应的减法函数并加上负号即可

#include
#include
#includeusing namespace std;//判断A是否大于B
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;       //两者相等
}//此时的算法是在确定A>B的基础上进行编写的
vector sub(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] - t;              //计算每一位需要A[i]-B[i]-tif(i < B.size()) t -= B[i];      C.emplace_back((t + 10) % 10); //如果求出来的值大于0,就是自身,如果小于零,就要借位+10,而这两种情况都可以用+10再模10进行一步运算if(t < 0) t = 1;       //如果t小于零,就说明借位了,需要赋值1,用于下一位的计算else t = 0;}while(C.size() > 1 && C.back() == 0) C.pop_back();   //去除前导零,例如11-11=00,需要把前面的0去掉同时保证如果答案就是0的时候则不去return C;
}int main(){string a,b;vector A,B;cin >> a >> b;for(int i = a.size() - 1; i >= 0; i--) A.emplace_back(a[i] - '0');for(int i = b.size() - 1; i >= 0; i--) B.emplace_back(b[i] - '0');if(cmp(A, B)){vector C = sub(A, B);       //如果A>B,就用A-Bfor(int i = C.size() - 1; i >= 0; i--) cout << C[i];}else{vector C = sub(B, A);       //如果A= 0; i--) cout << C[i];}return 0;
}

乘法

跟加法差不多,不难,需要注意的是对 ttt 的额外处理

#include
#include
#includeusing namespace std;vector mul(vector& A, int b){vector C;int t = 0;      //应该压入数组的每一位数值for(int i = 0; i < A.size() || t; i++){   //确保把T处理完if(i < A.size()) t += A[i] * b;   C.emplace_back(t % 10);t = t / 10;       //t不像加法,可能一次除不到位}return C;
}int main(){string a;vector A;int b;cin >> a >> b;for(int i = a.size() - 1; i >= 0; i--) A.emplace_back(a[i] - '0');vector C = mul(A, b);for(int i = C.size() - 1; i >= 0; i--) cout << C[i];return 0;
}

除法

除法要求商和余数,且商和其他三个运算不同,因为除法是从最高位开始计算的,所以要搞清对于每一位应该是从小到大进行操作还是从大到小

#include
#include
#includeusing namespace std;vector div(vector& A, int b, int& t){vector C;t = 0;                                    //应该压入数组的每一位数值for(int i = A.size() - 1; i >= 0; i--){   //和加减乘不同,除法要从最高位开始t = t * 10 + A[i];                    //算出每一步的被除数:当前位的数值*10+下一位C.emplace_back(t / b);                //入数组的是被除数除以除数t = t % b;                            //可能有余数,用于下一步的计算}reverse(C.begin(), C.end()); //由于最后是反着输出的,所以逆序一下while(C.size() > 1 && C.back() == 0) C.pop_back();  //跟减法一样,去除前导0return C;
}int main(){string a;vector A;int b;cin >> a >> b;for(int i = a.size() - 1; i >= 0; i--) A.emplace_back(a[i] - '0');int t;vector C = div(A, b, t);for(int i = C.size() - 1; i >= 0; i--) cout << C[i];cout << " " << t;return 0;
}

前缀和

一维

#include
using namespace std;const int N = 100010;
int Array[N],s[N];int main(){int n,m;cin >> n >> m;for(int i = 1; i <= n; i++){cin >> Array[i];s[i] = s[i-1] + Array[i];       //计算从下标1开始的前缀和}while (m--){int low, high;cin >> low >> high;cout << s[high] - s[low-1] << endl;    //计算任意下标范围内的元素之和}return 0;
}

二维

在这里插入图片描述

画个图就能理解

#include
using namespace std;const int N = 1010;
int Array[N][N],s[N][N];int main(){int n,m,q;cin >> n >> m >> q;for(int i = 1; i <= n; i++){for(int j = 1; j <= m; j++){cin >> Array[i][j];s[i][j] = s[i-1][j] + s[i][j-1] - s[i-1][j-1] + Array[i][j];    //计算前缀和}}while (m--){int x1,y1,x2,y2;cin >> x1 >> y1 >> x2 >> y2;cout << s[x2][y2] - s[x2][y1-1] - s[x1-1][y2] + s[x1-1][y1-1] << endl;   //求范围和}return 0;
}

相关内容

热门资讯

苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...