基础算法
会笑的小熊
在努力,在进步
展开
-
区间合并(贪心)
思路:1.按照所有区间的左端点从小到大进行排序2.扫描所有区间的过程中把所有可能有交集的区间进行合并题目:代码:#include<iostream>#include<vector>#include<algorithm>using namespace std;typedef pair<int,int> PII;vector<PII> segs;void merge(vector<PII>&原创 2022-02-03 16:27:47 · 444 阅读 · 0 评论 -
离散化(区间和)
整数的离散化:值域比较大(0~10^9),个数比较小(0~10^5),有些题目需要以这些值为下标来做,要把它们映射到从0开始的自然数,这些自然数就是其下标。这个过程就称作离散化注意两个问题:1.A[ ]中可能有重复元素,需要去重//数组排序并去重vector<int> alls; //存储所有待离散化的值sort(alls.begin(),alls.end()); //将所有值排序alls.erase(unique(alls.begin(),alls.end()));原创 2022-02-03 15:23:50 · 677 阅读 · 0 评论 -
位运算(二进制中1的个数)
位运算最常用的两种操作:1.求整数n二进制表示中第k位(从个位开始算)数字是几:n>>k&1先把第k位数字移到最后一位 n>>k 再看一下个位是几 x&12.lowbit操作:lowbit(x)原创 2022-01-29 23:05:36 · 998 阅读 · 0 评论 -
双指针算法(判断子序列)
思路:从前往后扫描b数组,每次扫描一个数后,判断一下b的当前数是否和a的当前数一样,如果一样,就将a的当前数匹配到b的当前数。遍历完b数组后,如果发现a数组中每一个数,都顺次找到了和它匹配的数,就找到了一个b的子序列和a相等。题目:代码:#include<iostream>using namespace std;const int N=1e6+10;int a[N],b[N];int n,m;int main(){ cin>>n>>.原创 2022-01-28 22:53:37 · 322 阅读 · 0 评论 -
双指针算法(数组元素的目标和)
思路://朴素做法:O(n^2)for(int i=0;i<n;i++){ for(int j=0;j<m;j++) { if(A[i]+B[j]==x) 输出; }}单调性:A,B两个数组单增,i往后移动时,i变大,那么只需j往前移动,j变小;//双指针算法:O(n+m)for(int i=0,j=m-1;i<n;i++){ while(j>=0&&A[i]+B[j]>原创 2022-01-28 21:42:11 · 482 阅读 · 0 评论 -
双指针算法(最长连续不重复子序列)
两种类型:1.两个指针分别指向两个序列>归并排序中把两个有序序列合并时2.两个指针指向一个序列>快速排序划分的过程,一个指针指向开头,一个指针指向结尾模板:for(i=0,j=0;i<0;i++){ while(j<i&&check(i,j))j++; //每组题目的具体逻辑}核心思想:将朴素算法O(n^2)优化到O(n)...原创 2022-01-28 21:13:57 · 466 阅读 · 0 评论 -
二维差分(差分矩阵)
类比二维前缀和以及一维差分给定原矩阵a[i,j],构造差分矩阵b[i,j],使矩阵a是矩阵b的前缀和差分核心操作:给以(x1,y1)为左上角,(x2,y2)为右下角的子矩阵的所有数a[i,j],加上c,等价于b[x1,y1]+=c,b[x1,y2+1]-=c,b[x2+1,y1]-=c,b[x2+1,y2+1]+=c题目:代码:#include<iostream>using namespace std;const int N=1010;int n,m,q;in.原创 2022-01-27 17:34:04 · 663 阅读 · 0 评论 -
一维差分法
差分是前缀和的逆运算给定一个数组a[1],a[2] ···a[n],构造b[1],b[2]···b[n]满足a[i]=b[1]+b[2]+···+b[i],即a数组是b数组的前缀和b[1]=a[1]b[2]=a[2]-a[1]b[3]=a[3]-a[2]···b[n]=a[n]-a[n-1]b数组就称为a数组的差分,数组a就称为数组b的前缀和给定一个区间[l,r],使a数组在[l,r]区间内所有数都加上c,只需b[l]+c,就会使a[l]+c,a[l+1]+c···a[n]+原创 2022-01-27 15:08:49 · 486 阅读 · 0 评论 -
二维前缀和(子矩阵的和)
考虑:1.s[ i , j ]如何计算:s[i,j]=s[i-1,j]+s[i,j-1]-s[i-1,j-1]+a[i,j]2.(x1,y1),(x2,y2)这一子矩阵中所有数的和如何计算:s[x2,y2]-s[x1-1,y2]-s[x2,y1-1]+s[x1-1,y1-1]题目:代码:#include<iostream>using namespace std;const int N=1010;int n,m,q;int a[N][N],s[N][N];..原创 2022-01-27 12:19:52 · 105 阅读 · 0 评论 -
一维前缀和
题目:代码:#include<iostream>using namespace std;const int N=1e5+10;int main(){ int n,m; cin>>n>>m; int a[N],s[N]; for(int i=1;i<=n;i++)cin>>a[i],s[i]=s[i-1]+a[i]; //前i项和公式 while(m--){ int l,.原创 2022-01-26 22:32:44 · 170 阅读 · 0 评论 -
高精度除法
题目:代码:#include<iostream>#include<vector>#include<algorithm>using namespace std;//A/B,商是C,余数是rvector<int> div(vector<int> &A,int b,int &r){ //r是引用 vector<int> C; r=0; for(int i=A.size(.原创 2022-01-26 21:43:31 · 142 阅读 · 0 评论 -
高精度乘法
高精度乘法可以类比高精度加法的进位,还要注意处理有高精度减法的前导0题目:代码:#include<iostream>#include<vector>using namespace std;vector<int> mul(vector<int> &A,int b){ vector<int> C; int t=0; //进位 for(int i=0;i<A.size()||t;.原创 2022-01-26 14:56:25 · 168 阅读 · 0 评论 -
高精度减法
首先可以了解一下C++ vector 使用方法基本操作(1)头文件#include<vector>.(2)创建vector对象,vector<int> vec;(3)尾部插入数字:vec.push_back(a);(4)使用下标访问元素,cout<<vec[0]<<endl;记住下标是从0开始的(5)返回尾元素的引用,vec.back()(6)删除向量中最后一个元素,vec.pop_back(a)思路:原创 2022-01-26 14:08:59 · 229 阅读 · 0 评论 -
高精度加法
首先可以了解一下c++ vector 使用方法基本操作(1)头文件#include<vector>.(2)创建vector对象,vector<int> vec;(3)尾部插入数字:vec.push_back(a);(4)使用下标访问元素,cout<<vec[0]<<endl;记住下标是从0开始的。(5)向量大小: vec.size();思路:大整数在c++中的存储方法:将每一位存到数组里面去,注意是倒..原创 2022-01-24 18:25:47 · 254 阅读 · 0 评论 -
二分(数的三次方根)
三次方根函数具有单调性>浮点数的二分:二分模板可以参看上一篇:二分(数的范围)题目:思路:确定边界-10000~10000(右边界不能小于1) 性质定为mid^3>=n 结果保留6位小数,保证(r-l)>10^-8次方(经验:比小数点多二比较保险)代码:#include<iostream>using namespace std;int main(){ double n; cin>>n; double l=-1原创 2022-01-23 22:51:41 · 176 阅读 · 0 评论 -
二分(数的范围)
整数二分:二分的本质并不是单调性,即有单调性一定可以用二分,但没有单调性也可能可以用二分;二分的本质其实是边界。简单来说:给定一个区间,在这区间上定义了某种性质,使得在右半边区间是满足的,在左半边区间是不满足的,如果可以找到这个性质,即将整个区间一分为二,使得一半满足,一半不满足,那么就可以采用二分来寻找这个性质的边界。既可以二分出红色边界点,也可以二分出绿色边界点,这又是两个不同的模板模板一(二分红色边界点):中间值mid=(l+r+1)/2(思考一下为什么+1),判断中间值是否...原创 2022-01-23 22:01:54 · 535 阅读 · 0 评论 -
归并排序(逆序对的数量)
逆序对的数量是对归并排序的应用,同样采用分治的思想。可以先看一下上一篇归并排序的思路。思路:首先还是把整个数组分为两个子数组,并进行递归排序使其成为有序序列。 考虑逆序对的三种情况(1.都在左序列 2.都在右序列 3.一个在左一个在右) 对于一个在左一个在右采用递归排序当q[i]>q[j]时,加入计时器res中,由于q[i]是有序递增,所以当q[i]>q[j]时,i后面(共mid-i+1个)的数也一定大于q[j]题目:代码:#include<iostream&.原创 2022-01-23 16:29:01 · 411 阅读 · 0 评论 -
归并排序算法
归并排序(MERGE-SORT)是利用归并的思想实现的排序方法,该算法采用经典的分治(divide-and-conquer)策略(分治法将问题分(divide)成一些小的问题然后递归求解,而治(conquer)的阶段则将分的阶段得到的各答案"修补"在一起,即分而治之)。思路:l,r分别为闭区间的左右边界,tem[]为临时数组,mid为中间值,将整数组分为左右两个子数组 分别递归处理左右两个数组,使其成为有序数组 i,j分别指向子数组的起点,比较其指向数的大小,将小的数存入临时数组中 将左右两个原创 2022-01-22 20:35:19 · 579 阅读 · 0 评论 -
快速排序(第k个数)
第k个数和快速排序代码模板差不多,只是在函数调用上加一个参数k,并在递归时判断一下。思路:先进行一次快排,使x左侧都<=x,x右侧都>=x; 计算x左侧数的个数:ls=j-l+1(注意+1) 判断k在x哪侧 ls>=k,则k在x左侧,只需递归x左侧 ls<k,则k在x右侧,只需递归x右侧题目:代码:#include<iostream>using namespace std;const int N=1e5+10; int n,k;i原创 2022-01-22 18:28:17 · 367 阅读 · 0 评论 -
快速排序算法
关于快速排序可以参看此篇博客https://blog.csdn.net/qq_28584889/category_8722100.html由于分享的链接对于快速排序讲解的足够详细,我就不再重复啦。根据所学视频,对于快排要在理解的基础上记住模板,同时在写代码时注意越界问题!#include<iostream>using namespace std;const int N = 1e5+10; //防止越界int n;int q[N];void quick_sort(in原创 2022-01-22 17:28:51 · 220 阅读 · 0 评论