全部来自acwing算法基础课
一、基础算法
1、快速排序
(1)快速排序
#include<iostream>
#include<cstring>
#include<algorithm>
#define N 100000+10
using namespace std;
int n,q[N];
void quick_sort(int q[],int l,int r){
if(l>=r)return;
int i=l-1,j=r+1,x=q[l+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++)
cin>>q[i];
quick_sort(q,1,n);
for(int i=1;i<=n;i++)
cout<<q[i]<<' ';
return 0;
}
(2)第k个数
#include<iostream>
#include<cstring>
#include<algorithm>
#define N 100000+10
using namespace std;
int n,k;
int q[N];
void quick_sort(int q[],int l,int r){
if(l>=r)return;
int i=l-1,j=r+1,x=q[l+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>>k;
for(int i=1;i<=n;i++)
cin>>q[i];
quick_sort(q,1,n);
cout<<q[k];
return 0;
}
2、归并排序
(1)归并排序
#include<iostream>
#include<cstring>
#include<algorithm>
#define N 100000+10
using namespace std;
int n,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 k=0,i=l,j=mid+1;
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];
}
int main(){
cin>>n;
for(int i=1;i<=n;i++)
cin>>q[i];
merge_sort(q,1,n);
for(int i=1;i<=n;i++)
cout<<q[i]<<' ';
return 0;
}
(2)逆序对的数量
#include<iostream>
#include<cstring>
#include<algorithm>
#define N 100000+10
#define ll long long
using namespace std;
ll n,ans=0;
ll q[N],tmp[N];
void merge_sort(ll q[],ll l,ll r){
if(l>=r)return;
ll mid=l+r>>1;
merge_sort(q,l,mid);
merge_sort(q,mid+1,r);
ll i=l,j=mid+1,k=0;
while(i<=mid&&j<=r)
if(q[i]<=q[j])tmp[k++]=q[i++];
else tmp[k++]=q[j++],ans+=mid-i+1;
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];
}
int main(){
cin>>n;
for(ll i=1;i<=n;i++)
cin>>q[i];
merge_sort(q,1,n);
cout<<ans;
return 0;
}
3、二分
(1)数的范围
#include<iostream>
#include<cstring>
#include<algorithm>
#define N 100000+10
using namespace std;
int n,q,k;
int a[N];
int bsearch_1(int l,int r){
while(l<r){
int mid=l+r>>1;
if(a[mid]>=k)r=mid;
else l=mid+1;
}
return l;
}
int bsearch_2(int l,int r){
while(l<r){
int mid=l+r+1>>1;
if(a[mid]<=k)l=mid;
else r=mid-1;
}
return l;
}
int main(){
cin>>n>>q;
for(int i=0;i<n;i++)
cin>>a[i];
for(int i=1;i<=q;i++){
cin>>k;
int ans1=bsearch_1(0,n-1);
int ans2=bsearch_2(0,n-1);
if(a[ans1]!=k||a[ans2]!=k)
ans1=-1,ans2=-1;
cout<<ans1<<" "<<ans2<<endl;
}
return 0;
}
(2)数的三次方根
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
double n;
int main(){
scanf("%lf",&n);
double l=-100,r=100;
while(r-l>1e-8){
double mid=(l+r)/2;
if(mid*mid*mid>=n)r=mid;
else l=mid;
}
printf("%.6lf",l);
return 0;
}
4、高精度
(1)高精度加法
#include<bits/stdc++.h>
#define N 100000+10
using namespace std;
char sa[N],sb[N];
int a[N],b[N],c[N];
int la,lb,len;
int main(){
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(c,0,sizeof(c));
cin>>sa>>sb;
la=strlen(sa);
lb=strlen(sb);
for(int i=0;i<la;i++)a[la-i-1]=sa[i]-'0';
for(int i=0;i<lb;i++)b[lb-i-1]=sb[i]-'0';
len=max(la,lb);
for(int i=0;i<=len;i++){
c[i]+=a[i]+b[i];
c[i+1]=c[i]/10;
c[i]%=10;
}
while(c[len]==0)len--;
for(int i=len;i>=0;i--)
cout<<c[i];
return 0;
}
(2)高精度减法
#include<iostream>
#include<cstring>
#define N 100000+10
using namespace std;
int a[N],b[N],c[N];
char sa[N],sb[N];
int la,lb,lmax;
bool compare(int a[],int b[]){
if(la>lb)return true;
if(la<lb){cout<<"-";return false;}
for(int i=lmax-1;i>=0;i--)
if(a[i]<b[i]){
cout<<"-";
return false;
}
else if(a[i]>b[i])return true;
return true;
}
void sub(int a[],int b[]){
for(int i=0;i<lmax;i++){
c[i]=a[i]-b[i];
if(c[i]<0)c[i]+=10,a[i+1]-=1;
}
while(c[lmax]==0)lmax--;
for(int i=lmax;i>=0;i--)
cout<<c[i];
if(lmax<0)cout<<c[0];
}
int main(){
cin>>sa>>sb;
la=strlen(sa);
lb=strlen(sb);
lmax=max(la,lb);
for(int i=0;i<la;i++)a[la-i-1]=sa[i]-'0';
for(int i=0;i<lb;i++)b[lb-i-1]=sb[i]-'0';
if(compare(a,b))sub(a,b);
else sub(b,a);
return 0;
}
(3)高精度乘法
#include<iostream>
#include<cstring>
#define N 100000+10
using namespace std;
int a[N],b,c[N];
char sa[N];
int la,len;
int main(){
cin>>sa>>b;
la=strlen(sa);
for(int i=0;i<la;i++)a[la-i-1]=sa[i]-'0';
len=la+4;
for(int i=0;i<len;i++){
c[i]+=a[i]*b;
c[i+1]=c[i]/10;
c[i]%=10;
}
while(c[len]==0)len--;
for(int i=len;i>=0;i--)
cout<<c[i];
if(len<0)cout<<c[0];
return 0;
}
(4)高精度除法
#include<iostream>
#include<cstring>
#define N 100000+10
using namespace std;
int a[N],b,c[N],d;
char sa[N];
int la,len=0;
int main(){
cin>>sa>>b;
la=strlen(sa);
for(int i=0;i<la;i++)a[i]=sa[i]-'0';
d=0;
for(int i=0;i<la;i++){
d=d*10+a[i];
c[i]=d/b;
d%=b;
}
while(c[len]==0)len++;
for(int i=len;i<la;i++)
cout<<c[i];
if(len>=la)cout<<c[la];
cout<<endl<<d;
return 0;
}
5、前缀和与差分
(1)前缀和
#include<bits/stdc++.h>
#define N 100000+10
using namespace std;
int n,m;
int sum[N];
int l,r;
int main(){
sum[0]=0;
cin>>n>>m;
for(int i=1;i<=n;i++){
int x;cin>>x;
sum[i]=sum[i-1]+x;
}
for(int i=1;i<=m;i++){
cin>>l>>r;
cout<<sum[r]-sum[l-1]<<endl;
}
return 0;
}
(2)子矩阵的和
#include<iostream>
#include<cstring>
#include<algorithm>
#define N 1000+10
using namespace std;
int n,m,q;
int sum[N][N];
int main(){
cin>>n>>m>>q;
memset(sum,0,sizeof sum);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
int x;cin>>x;
sum[i][j]=x+sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
}
for(int i=1;i<=q;i++){
int a,b,c,d;cin>>a>>b>>c>>d;
int ans=sum[c][d]-sum[a-1][d]-sum[c][b-1]+sum[a-1][b-1];
cout<<ans<<endl;
}
return 0;
}
(3)差分
#include<iostream>
#include<cstring>
#include<algorithm>
#define N 100000+10
using namespace std;
int n,m,l,r,c;
int a[N],b[N];
int main(){
cin>>n>>m;
a[0]=0;
for(int i=1;i<=n;i++){
cin>>a[i];
b[i]=a[i]-a[i-1];
}
for(int i=1;i<=m;i++){
cin>>l>>r>>c;
b[l]+=c;b[r+1]-=c;
}
int x=0;
for(int i=1;i<=n;i++){
x+=b[i];
cout<<x<<' ';
}
return 0;
}
(4)差分矩阵
#include<iostream>
#include<cstring>
#include<algorithm>
#define N 1000+10
using namespace std;
int n,m,q;
int x[N][N],y[N][N];
int a,b,c,d;
int t;
int main(){
cin>>n>>m>>q;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
cin>>x[i][j];
y[i][j]=x[i][j]-x[i-1][j]-x[i][j-1]+x[i-1][j-1];
}
for(int i=1;i<=q;i++){
cin>>a>>b>>c>>d>>t;
y[a][b]+=t;
y[c+1][b]-=t;
y[a][d+1]-=t;
y[c+1][d+1]+=t;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
x[i][j]=y[i][j]+x[i-1][j]+x[i][j-1]-x[i-1][j-1];
cout<<x[i][j]<<' ';
}
cout<<endl;
}
return 0;
}
6、双指针算法
(1)最长连续不重复子序列
#include<iostream>
#include<algorithm>
#define N 100000+10
using namespace std;
int n;
int a[N],cnt[N];
int i=1,j=1;
int ans=0;
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(;j<=n;j++){
cnt[a[j]]++;
while(i<j&&cnt[a[j]]>1)cnt[a[i++]]--;
ans=max(ans,j-i+1);
}
printf("%d",ans);
return 0;
}
(2)数组元素的目标和
#include<iostream>
#include<algorithm>
#define N 100000+10
using namespace std;
int n,m,x;
int a[N],b[N];
int i,j;
int main(){
scanf("%d%d%d",&n,&m,&x);
for(int i=0;i<n;i++)scanf("%d",&a[i]);
for(int i=0;i<m;i++)scanf("%d",&b[i]);
for(int i=0,j=m-1;i<n;i++){
while(j>=0&&a[i]+b[j]>x)j--;
if(j>=0&&a[i]+b[j]==x)printf("%d %d",i,j);
}
return 0;
}
7、位运算
(1)二进制中1的个数
#include<iostream>
using namespace std;
void work(int a){
int ans=0;
while(a){
if(a&1)ans++;
a>>=1;
}
printf("%d ",ans);
}
int main(){
int n;scanf("%d",&n);
while(n--){
int a;
scanf("%d",&a);
work(a);
}
return 0;
}
8、离散化
(1)区间和
#include<iostream>
#include<vector>
#include<algorithm>
#define N 300000+10
#define PII pair<int,int>
using namespace std;
int n,m;
int a[N],s[N];
vector<int>alls;
vector<PII>add,query;
int find(int x){
int l=0,r=alls.size()-1;
while(l<r){
int mid=l+r>>1;
if(alls[mid]>=x)r=mid;
else l=mid+1;
}
return r+1;
}
vector<int>::iterator unique(vector<int> &a){
int j=0;
for(int i=0;i<a.size();i++)
if(!i||a[i]!=a[i-1])
a[j++]=a[i];
return a.begin()+j;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++){
int x,c;scanf("%d%d",&x,&c);
add.push_back({x,c});
alls.push_back(x);
}
for(int i=0;i<m;i++){
int l,r;scanf("%d%d",&l,&r);
query.push_back({l,r});
alls.push_back(l);
alls.push_back(r);
}
sort(alls.begin(),alls.end());
alls.erase(unique(alls),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);
printf("%d\n",s[r]-s[l-1]);
}
return 0;
}
9、区间合并
(1)区间合并
#include<iostream>
#include<algorithm>
#define N 100000+10
using namespace std;
int n;
int ans=1;
struct node{
int l,r;
}a[N];
bool cmp(node a,node b){
return a.l<b.l;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d%d",&a[i].l,&a[i].r);
sort(a+1,a+n+1,cmp);
int end=a[1].r;
for(int i=2;i<=n;i++){
if(a[i].l>end)end=a[i].r,ans++;
else end=max(end,a[i].r);
}
printf("%d",ans);
return 0;
}
二、数据结构
1、单链表
(1)单链表
#include<bits/stdc++.h>
#define N 100000+10
using namespace std;
int m,n=0;
int num[N],nxt[N];
int main(){
cin>>m;
memset(num,0,sizeof(num));
memset(nxt,0,sizeof(nxt));
for(int i=1;i<=m;i++){
char ch;
cin>>ch;
if(ch=='H'){
int x;cin>>x;
n++;num[n]=x;
nxt[n]=nxt[0];
nxt[0]=n;
}
if(ch=='D'){
int k;cin>>k;
nxt[k]=nxt[nxt[k]];
}
if(ch=='I'){
int k,x;cin>>k>>x;
n++;num[n]=x;
nxt[n]=nxt[k];
nxt[k]=n;
}
}
int t=0;
while(nxt[t]!=0){
cout<<num[nxt[t]]<<' ';
t=nxt[t];
}
return 0;
}
2、双链表
(1)双链表
#include<bits/stdc++.h>
#define N 100000+10
using namespace std;
int m,n=0;
int num[N],pre[N],nxt[N];
char ch;
int main(){
cin>>m;
for(int i=1;i<=m;i++){
cin>>ch;
if(ch=='L'){
int x;cin>>x;
n++;num[n]=x;
pre[nxt[0]]=n;
nxt[n]=nxt[0];
nxt[0]=n;
pre[n]=0;
}
if(ch=='R'){
int x;cin>>x;
n++;num[n]=x;
nxt[pre[0]]=n;
pre[n]=pre[0];
pre[0]=n;
nxt[n]=0;
}
if(ch=='D'){
int k;cin>>k;
nxt[pre[k]]=nxt[k];
pre[nxt[k]]=pre[k];
}
if(ch=='I'){
cin>>ch;
if(ch=='L'){
int k,x;cin>>k>>x;
n++;num[n]=x;
nxt[n]=k;pre[n]=pre[k];
pre[k]=n;nxt[pre[n]]=n;
}
if(ch=='R'){
int k,x;cin>>k>>x;
n++;num[n]=x;
pre[n]=k;nxt[n]=nxt[k];
nxt[k]=n;pre[nxt[n]]=n;
}
}
}
int t=0;
while(nxt[t]!=0){
cout<<num[nxt[t]]<<' ';
t=nxt[t];
}
return 0;
}
3、栈
(1)模拟栈
#include<iostream>
#include<cstring>
#include<algorithm>
#define N 100000+10
using namespace std;
int m,x,n=0;
int a[N];
char s[10];
void push(int x){
n++;
a[n]=x;
}
void pop(){
n--;
}
void empty(){
if(n==0)printf("YES\n");
else printf("NO\n");
}
void query(){
printf("%d\n",a[n]);
}
int main(){
scanf("%d",&m);
while(m--){
cin>>s;
if(s[0]=='p'){
if(s[1]=='u'){
scanf("%d