模板题——快排、归并、二分

这篇博客涵盖了多种排序算法的实现,包括快速排序和归并排序,并提供了它们的模板代码。此外,还讨论了整数二分查找以及浮点数二分的场景应用。文章还涉及到了一些实际问题,如机器人跳跃、割绳子问题和四平方和的求解策略,展示了如何运用二分查找解决实际问题。
摘要由CSDN通过智能技术生成

1.快速排序模板

#include <bits/stdc++.h>

using namespace std;

const int N = 1000010;

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)/2];
    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()
{
    int n,k;
    scanf("%d%d", &n,&k);

    for (int i = 0; i < n; i ++ ) scanf("%d", &q[i]);

    quick_sort(q, 0, n - 1);

    printf("%d\n", q[k-1]);

    return 0;
}

2.归并排序模板

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N=1e6+9;
int n;
int a[N],tmp[N];
void mergesort(int q[],int l,int r)
{
    if(l>=r) return ;
    int mid=l+r>>1;
    mergesort(q,l,mid);
    mergesort(q,mid+1,r);
    int 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++];
    while(i<=mid) tmp[k++]=q[i++];
    while(j<=r) tmp[k++]=q[j++];
    for(int i=l,j=0;i<=r;i++,j++) q[i]=tmp[j];
}
int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++)
        scanf("%d",&a[i]);
    mergesort(a,0,n-1);
     for(int i=0;i<n;i++) cout<<a[i]<<" ";
    return 0;
}

3.归并排序模板【逆序数对】

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+9;
int n;
int a[N],tmp[N];
ll mergesort(int q[],int l,int r)
{
    if(l>=r) return 0;
    int mid=l+r>>1;
    ll res=mergesort(q,l,mid)+mergesort(q,mid+1,r);
    int 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++];res+=mid-i+1;}
    while(i<=mid) tmp[k++]=q[i++];
    while(j<=r) tmp[k++]=q[j++];
    for(int i=l,j=0;i<=r;i++,j++) q[i]=tmp[j];
    return res;
}
int main()
{
    scanf("%d",&n);
    for(int i=0;i<n;i++)
        scanf("%d",&a[i]);
    printf("%lld\n",mergesort(a,0,n-1));
    return 0;
}

4.整数二分【Mid分别在两个区间的不同模板】

用来查找某个整数是否在序列中存在,时间复杂度O( n 2 n^2 n2logn)

#include <bits/stdc++.h>

using namespace std;
const int N=1000010;
int n,t,k;
int q[N];
int main()
{
   scanf("%d%d",&n,&t);
   for(int i=0;i<n;i++)
    scanf("%d",&q[i]);
    while(t--)
    {
        scanf("%d",&k);
        int l=0,r=n-1;
        while(l<r)
        {
           int mid=l+r>>1;
           if(q[mid]>=k) r=mid;
           else l=mid+1;
        }
        if(q[l]!=k) printf("-1 -1\n");//q[l]=q[r]
        else
        {
            cout<<l<<" ";
            int l=0,r=n-1;
            while(l<r)
            {
                int mid=l+r+1>>1;
                if(q[mid]<=k) l=mid;
                else r=mid-1;
            }
            cout<<l<<endl;
        }
    }
    return 0;
}

分巧克力

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N=100010;
int n,k;
int h[N],w[N];

int check(int mid)
{
    ll res=0;
    for(int i=0;i<n;i++)
    res+=h[i]/mid*(w[i]/mid);
    if(res>=k) return true;
    return false;
}
int main()
{
    cin>>n>>k;
    for(int i=0;i<n;i++) scanf("%d%d",&h[i],&w[i]);
    int l=1,r=1e5;
    while(l<r)
    {
        int mid=l+r+1>>1;
        if(check(mid)) l=mid;
        else r=mid-1;
    }
    printf("%d\n",r);
    return 0;
}

机器人跳跃问题

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>

using namespace std;
const int N=100010;
int n,h[N];
bool check(int e)
{
    for(int i=1;i<=n;i++)
    {
        e=2*e-h[i];
        if(e>=1e5) return true;
        if(e<0) return false;
    }
    return true;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&h[i]);
    int l=0,r=1e5;
    while(l<r)
    {
        int mid=l+r>>1;
        if(check(mid)) r=mid;
        else l=mid+1;
    }
    printf("%d\n",r);
    return 0;
}

1221.四平方和
纯暴力枚举三次的O( n 3 n^3 n3)代码会被卡掉,哈希算法在本题中是最坏情况,算法本身O( N 2 N^2 N2),因此也会超时

#include <cstring>
#include <iostream>
#include <algorithm>
#include <cmath>

using namespace std;
const int N = 2500010;
struct Sum
{
    int s, c, d;
    bool operator< (const Sum &t)const
    {
        if (s != t.s) return s < t.s;
        if (c != t.c) return c < t.c;
        return d < t.d;
    }
}sum[N];
int n, m;
int main()
{
    cin >> n;

    for (int c = 0; c * c <= n; c ++ )
        for (int d = c; c * c + d * d <= n; d ++ )
            sum[m ++ ] = {c * c + d * d, c, d};
    sort(sum, sum + m);
    for (int a = 0; a * a <= n; a ++ )
        for (int b = 0; a * a + b * b <= n; b ++ )
        {
            int t = n - a * a - b * b;
            int l = 0, r = m - 1;
            while (l < r)
            {
                int mid = l + r >> 1;
                if (sum[mid].s >= t) r = mid;
                else l = mid + 1;
            }
            if (sum[l].s == t)
            {
                printf("%d %d %d %d\n", a, b, sum[l].c, sum[l].d);
                return 0;
            }
        }

    return 0;
}

5.浮点数二分

#include <bits/stdc++.h>

using namespace std;

int main()
{
    double n;
    scanf("%lf",&n);
    double l=-10000,r=10000;
    while(r-l>1e-8)
    {
        double mid=(l+r)/2;
        if(pow(mid,3)>=n) r=mid;
        else l=mid;
    }
    printf("%lf\n",l);
    return 0;
}

割绳子:绳子的根数一定定义成整数!

#include <bits/stdc++.h>

using namespace std;
const int N=100010;
double a[N];
int n,m;
bool check(double mid)
{
    int res=0;
    for(int i=0;i<n;i++)
    res+=a[i]/mid;
    if(res>=m) return true;
    return false;
}
int main()
{
    cin>>n>>m;
    for(int i=0;i<n;i++) scanf("%lf",&a[i]);
    double l=0,r=1e9;
    while(r-l>=1e-3)
    {
        double mid=(l+r)/2;
        if(check(mid)) l=mid;
        else r=mid;
    }
    printf("%.2f\n",r);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值