初赛模板复习

全部来自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
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值