bzoj5277 [Usaco2018 Open]Out of Sorts(智商题)

本文探讨了一种结合冒泡排序与快速排序的方法,通过分析如何确定每个元素完成排序所需趟数来优化整体排序过程。具体地,文章介绍了一个算法实现,该算法能够有效地计算出每个元素在排序过程中被调整到位所需的最小趟数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

首先我们注意到,对一个序列按分割点分开以后分别冒泡其实就相当于对整个序列进行冒泡。每一个元素都会对复杂度贡献1,除非一个元素两边的分割点都出现了。因此我们可以完全忽略快排的递归过程。只需考虑每个元素在经历几趟冒泡排序之后两边的分割点都出现了。

考虑一个分割点,不妨就是在i,i+1之间的这个分割点,他在几趟冒泡排序之后会出现呢?出现了这个分割点,说明前i小的元素都已经在前i个了,我们记前i小的元素一开始最大的下标为x,则在x-i趟冒泡之后就会把x挪到前i个位置(因为每趟冒泡一定会使x的下标-1)。也就是说i,i+1之间的分割点会在x-i趟冒泡之后出现。而第i个元素的贡献就是它左右分割点出现时间的最大值。

还要注意一些细节,比如某个元素两边的分割点出现时间为0,即一趟冒泡也没进行之前就已经排好了,但是我们的函数过程是一上来一定先冒泡一遍,因此也要贡献1.(当然,除非n=1,答案为0,直接退出)

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 100010
#define ll long long
#define inf 0x3f3f3f3f
inline char gc(){
    static char buf[1<<16],*S,*T;
    if(S==T){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;}
    return *S++;
}
inline int read(){
    int x=0,f=1;char ch=gc();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
    return x*f;
}
int n,cnt[N];ll ans=0;
struct node{
    int id,x;
    friend bool operator<(node a,node b){return a.x==b.x?a.id<b.id:a.x<b.x;}
}a[N];
int main(){
//  freopen("a.in","r",stdin);
    n=read();if(n==1){puts("0");return 0;}
    for(int i=1;i<=n;++i) a[i].x=read(),a[i].id=i;
    sort(a+1,a+n+1);int mx=0;
    for(int i=1;i<n;++i){
        mx=max(mx,a[i].id);
        cnt[i]=mx-i;
    }for(int i=1;i<=n;++i){
        int x=max(cnt[i],cnt[i-1]);
        if(!x) ++x;ans+=x;
    }printf("%lld\n",ans);
    return 0;

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值