演算法模板整理(一)

清風紫雪發表於2020-11-09

1.歸併排序板子(包含求逆序對個數):

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int a[maxn],tmp[maxn];
int ans=0;

void merge_sort(int l,int r)
{
    if(l>=r)
        return;
    int mid=l+r>>1;
    merge_sort(l,mid);
    merge_sort(mid+1,r);
    int i=l,j=mid+1,k=0;
    while(i<=mid&&j<=r)
    {
        if(a[i]<=a[j])
            tmp[k++]=a[i++];
        else
        {
          ans+=mid-i+1;
          tmp[k++]=a[j++];
        }
    }
    while(i<=mid)
        tmp[k++]=a[i++];
    while(j<=r)
        tmp[k++]=a[j++];
    for(i=l,j=0;i<=r;i++,j++)
        a[i]=tmp[j];
}


int main()
{
    int i,j,n;
    cin>>n;
    for(i=0;i<n;i++)
        cin>>a[i];
    merge_sort(0,n-1);
    cout<<ans<<endl;
    return 0;
}

2.字首和陣列板子

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3+10;
int n,m,q;
int a[maxn][maxn],sum[maxn][maxn];

int main()
{
    int i,j;
    int x,y,x2,y2;
    cin>>n>>m>>q;
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=m;j++)
        {
            cin>>a[i][j];
            sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+a[i][j];
        }
    }
    while(q--)
    {
        cin>>x>>y>>x2>>y2;
        cout<<sum[x2][y2]-sum[x-1][y2]-sum[x2][y-1]+sum[x-1][y-1]<<endl;
    }
    return 0;
}

3.差分陣列板子

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int n,m;
int a[maxn],b[maxn];

void insert(int l,int r,int c)
{
    b[l]+=c;
    b[r+1]-=c;
}

int main()
{
    int i,j,n,m;
    cin>>n>>m;
    for(i=1;i<=n;i++)
        cin>>a[i];
    for(i=1;i<=n;i++)
        insert(i,i,a[i]);
    while(m--)
    {
        int l,r,c;
        cin>>l>>r>>c;
        insert(l,r,c);
    }
    for(i=1;i<=n;i++)
    {
        b[i]+=b[i-1];
        cout<<b[i]<<" ";
    }
    cout<<endl;
    return 0;
}

4.差分矩陣板子

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e3+10;
int n,m,q;
int a[maxn][maxn],b[maxn][maxn];

void insert(int x1,int y1,int x2,int y2,int c)
{
    b[x1][y1]+=c;
    b[x2][y1+1]-=c;
    b[x1][y2+1]-=c;
    b[x2+1][y2+1]+=c;
}

int main()
{
    int i,j;
    cin>>n>>m>>q;
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=m;j++)
        {
            cin>>a[i][j];
            insert(i,j,i,j,a[i][j]);
        }
    }
    while(q--)
    {
        int x1,y1,x2,y2,c;
        cin>>x1>>y1>>x2>>y2>>c;
        insert(x1,y1,x2,y2,c);
    }
    for(i=1;i<=n;i++)
    {
        for(j=1;j<=m;j++)
        {
            b[i][j]+=b[i-1][j]+b[i][j-1]-b[i-1][j-1];
            cout<<b[i][j]<<" ";
        }
    }
    cout<<endl;
    return 0;
}

 5.二分板子(當出現l=mid,需要將mid=(l+r+1)/2,做加1處理,否則會陷入死迴圈)

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int n,q,k;
int a[maxn];


int main()
{
    int i,j;
    cin>>n>>q;
    for(i=0;i<n;i++)
        cin>>a[i];
    while(q--)
    {
        cin>>k;
        int l=0,r=n-1,mid;
        while(l<r)
        {
            mid=(l+r)/2;
            if(a[mid]>=k)
                r=mid;
            else
                l=mid+1;
        }
        if(a[r]==k)
        {
            cout<<r<<" ";
            l=r;r=n-1;
            while(l<r)
            {
                mid=(l+r+1)/2;
                if(a[mid]<=k)
                    l=mid;
                else
                    r=mid-1;
            }
            cout<<l<<endl;
        }
        else
        {
            cout<<"-1 -1"<<endl;
        }
    }

    return 0;
}

6.雙指標板子(i是快指標,j是慢指標,j<i)

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int n;
int a[maxn];

int main()
{
    int i,j;
    cin>>n;
    map<int,int>s;
    for(i=0;i<n;i++)
        cin>>a[i];
    int ans=0;
    for(i=0,j=0;i<n;i++)
    {
        s[a[i]]++;
        while(j<i&&s[a[i]]>1)
        {
            s[a[j]]--;
            j++;
        }
        ans=max(ans,i-j+1);
    }
    cout<<ans;
    return 0;
}

小知識Tip

補充一個小Tip:STL裡的陣列全排例可以用這個函式:std::next_permutation()來展示陣列裡的所有全排列

另一個小Tip:約瑟夫環的騷操作:s=(s+M)%i,這個可以快速的求出最後留下的人的號碼,附上程式碼

#include <bits/stdc++.h>
using namespace std;
 int M;
int main()
{
    int n,i, s = 0;
    scanf("%d%d", &n,&M);
    for ( i = 2; i <= n; ++i)
    {
        s = (s+M)%i;
        cout<<s<<endl;
    }
    printf("%d\n", s+1);
    return 0;
}

 

相關文章