目录
快速排序
归并排序
二分
整数二分
浮点数二分
前缀和
一维前缀和
二维前缀和
差分
一维差分
二维差分
双指针
位运算
离散化
区间合并
快速排序
方法一:定义两个新数组,a[ ],b[ ],每次将大于x的放到a中,小于x的放到b中,再将其复制到q中
方法二:双指针,i=l-1,j=r+1,移动i、j,当q[i]小于x时,i++;当q[j]>x时,j--;直到都找到不满足的数字时,交换位置
#include <iostream>
using namespace std;
const int N=1e5+10;
int q[N];
int n;
void quick_sort(int q[],int l,int r)
{
if(l>=r) return;
int x=q[(l+r)/2];
int i=l-1,j=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);
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++) scanf("%d",&q[i]);
quick_sort(q,1,n);
for(int i=1;i<=n;i++) printf("%d ",q[i]);
return 0;
}
归并排序
1、选取中间位置,将整个数组一分为二
2、递归处理,直到保证[l,mid],[mid+1,r]都为有序的数组
3、合并数组,二合一
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=1e6+10;
int n;
int q[N],tmp[N];
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 i=l,j=mid+1;
int k=0;
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,k=1;i<=r;i++,k++) q[i]=tmp[k];
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++) scanf("%d",&q[i]);
merge_sort(q,1,n);
for(int i=1;i<=n;i++) printf("%d ",q[i]);
return 0;
}
二分
整数二分
模板:
[l,r]划分为[l,mid],[mid+1,r]
while(l<r)
{
int mid=l+r>>1;
if(check()) l=mid+1;
else r=mid;
}
[l,r]划分为[l,mid-1],[mid,r]
while(l<r)
{
int mid=l+r+1>>1;
if(check()) l=mid;
else r=mid-1;
}
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=1e5+10;
int n,k,x;
int a[N];
int main()
{
cin>>n>>k;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
while(k--)
{
cin>>x;
int l=1,r=n;
while(l<r)
{
int mid=l+r>>1;
if(a[mid]>=x) r=mid;
else l=mid+1;
}
if(a[l]!=x) cout<<"-1 -1"<<endl;
else
{
cout<<l-1<<" ";
r=n;
while(l<r)
{
int mid=l+r+1>>1;
if(a[mid]>x) r=mid-1;
else l=mid;
}
cout<<r-1<<endl;
}
}
return 0;
}
浮点数二分
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
double x;
int main()
{
cin>>x;
double l=-10000.0,r=10000.0;
while(r-l>=1e-8)
{
double mid=(l+r)/2;
if(mid*mid*mid>x) r=mid;
else l=mid;
}
printf("%lf",l);
return 0;
}
前缀和
一维前缀和
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=1e6+10;
int n,m;
int s[N];
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
int x;
scanf("%d",&x);
s[i]=s[i-1]+x;
}
while(m--)
{
int l,r;
scanf("%d%d",&l,&r);
cout<<s[r]-s[l-1]<<endl;
}
return 0;
}
二维前缀和
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=1010;
int n,m,q;
int s[N][N];
int main()
{
cin>>n>>m>>q;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
int x;
scanf("%d",&x);
s[i][j]=s[i][j-1]+s[i-1][j]+x-s[i-1][j-1];
}
}
while(q--)
{
int x1,x2,y1,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
cout<<s[x2][y2]-s[x2][y1-1]-s[x1-1][y2]+s[x1-1][y1-1]<<endl;
}
return 0;
}
差分
实现对区间[l,r]内的所有值+c;
a[ ],b[ ]
将a[ ]当做b[ ]的前缀和数组,b[i]=a[i-]-a[i-1]
=>a[i]=b[1]+b[2]+......+b[i]
对a[l].......a[r]均+c:b[l]+=c,b[r+1]-=c;
在对b[ ]求一遍前缀和
一维差分
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=1e5+10;
int a[N],s[N];
int n,m;
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
scanf("%d",&s[i]);
a[i]=s[i]-s[i-1];
}
while(m--)
{
int l,r,c;
scanf("%d%d%d",&l,&r,&c);
a[l]+=c;
a[r+1]-=c;
}
for(int i=1;i<=n;i++)
{
s[i]=s[i-1]+a[i];
}
for(int i=1;i<=n;i++) printf("%d ",s[i]);
return 0;
}
二维差分
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=1010;
int n,m,q;
int a[N][N],b[N][N];
void insert(int x1,int y1,int x2,int y2,int c)
{
b[x1][y1]+=c;
b[x2+1][y1]-=c;
b[x1][y2+1]-=c;
b[x2+1][y2+1]+=c;
}
int main()
{
cin>>n>>m>>q;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cin>>a[i][j];
insert(i,j,i,j,a[i][j]);
}
}
while(q--)
{
int x1,x2,y1,y2,c;
cin>>x1>>y1>>x2>>y2>>c;
insert(x1,y1,x2,y2,c);
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
b[i][j]+=b[i-1][j]+b[i][j-1]-b[i-1][j-1];
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cout<<b[i][j]<<" ";
}
cout<<endl;
}
return 0;
}
双指针
1、指向两个序列(eg归并排序)
2、指向一个序列(eg.快排)
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=1e5+10;
int a[N],n,s[N];
int res;
int main()
{
cin>>n;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1,j=1;i<=n;i++)
{
s[a[i]]++;
while(j<=i&&s[a[i]]>1) s[a[j++]]--;
res=max(res,i-j+1);
}
cout<<res;
return 0;
}
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=1e5+10;
int n,m,x;
int a[N],b[N];
int main()
{
cin>>n>>m>>x;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=m;i++) scanf("%d",&b[i]);
// for(int i=1;i<=n;i++)
// {
// for(int j=1;j<=m;j++)
// {
// if(a[i]+b[j]==x)
// {
// cout<<i-1<<" "<<j-1;
// break;
// }
// }
// }
for(int i=1,j=m;i<=n;i++)
{
while(j>=1&&a[i]+b[j]>x) j--;
if(j>=1&&a[i]+b[j]==x)
{
cout<<i-1<<" "<<j-1;
break;
}
}
return 0;
}
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N=1e5+10;
int n,m;
int a[N],b[N];
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=m;i++) scanf("%d",&b[i]);
int i=1,j=1;
while(i<=n&&j<=m)
{
if(a[i]==b[j]) i++;
j++;
}
if(i==n+1) cout<<"Yes";
else cout<<"No";
return 0;
}
位运算
//返回x的最后一位1
int lowbit(int x)
{
return x&-x;
}
//判断x的第k位是否为1
if(x>>k&1)
离散化
离散化的步骤
1、排序
2、去重
3、找到x离散化后的位置(二分)
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
typedef pair<int, int> PII;
const int N=3e5+10;
int n,m;
int a[N],s[N];//s是a的前缀和
vector<int> alls;//待离散化的数组
vector<PII> add,query;
int find(int x)//找到x离散化后的坐标
{
int l=0,r=alls.size()-1;
while(l<r)
{
int mid=l+r+1>>1;
if(alls[mid]>x) r=mid-1;
else l=mid;
}
return l+1;
}
int main()
{
cin>>n>>m;
for(int i=1;i<=n;i++)
{
int x,c;
cin>>x>>c;
add.push_back({x,c});
alls.push_back(x);
}
for(int i=1;i<=m;i++)
{
int l,r;
cin>>l>>r;
query.push_back({l,r});
alls.push_back(l);
alls.push_back(r);
}
//排序
sort(alls.begin(),alls.end());
//去重
alls.erase(unique(alls.begin(),alls.end()),alls.end());
//处理操作
for(auto item:add)
{
int x=find(item.first);
a[x]+=item.second;
}
//处理前缀和
for(int i=1;i<=alls.size();i++)
{
s[i]=s[i-1]+a[i];
}
//处理查询
for(auto item:query)
{
int l=find(item.first),r=find(item.second);
cout<<s[r]-s[l-1]<<endl;
}
return 0;
}
区间合并
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
typedef pair<int, int> PII;
int n;
vector<PII> segs;
void merge(vector<PII> &segs)
{
vector<PII> res;
int l=-2e9,r=-2e9;
sort(segs.begin(),segs.end());
for(auto item:segs)
{
if(item.first>r)
{
if(l!=-2e9) res.push_back({l,r});
l=item.first,r=item.second;
}
else
{
r=max(r,item.second);
}
}
if(r!=-2e9) res.push_back({l,r});
segs=res;
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
{
int l,r;
scanf("%d%d",&l,&r);
segs.push_back({l,r});
}
merge(segs);
cout<<segs.size()<<endl;
return 0;
}