bzoj 5277: [Usaco2018 Open]Out of Sorts【冒泡排序瞎搞】
首先考虑快排的递归什么时候停下,显然是当前段只剩下一个数了,也就是一个数两边出现分隔符
然后再考虑计算冒泡长度这个操作,因为有分割,所以我们可以把这些放到一起冒泡,这和递归每个区间冒泡是等价的
所以答案就是一个数被动了几次,也就是他两边的分隔符出现的最晚时间
在冒泡排序中,每次冒泡,一个数如果前面有比他大的,就会往前面动一步 否则就会往后移到第一个比他大的那个数的前面
所以分隔符i出现的时间就是最右的小于i的数的位置到i的距离
然后直接计算答案即可
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=100005;
long long n,f[N],g[N],mx,ans;
struct qwe
{
int v,id;
}a[N];
bool cmp(const qwe &a,const qwe &b)
{
return a.v<b.v||(a.v==b.v&&a.id<b.id);
}
int read()
{
int r=0,f=1;
char p=getchar();
while(p>'9'||p<'0')
{
if(p=='-')
f=-1;
p=getchar();
}
while(p>='0'&&p<='9')
{
r=r*10+p-48;
p=getchar();
}
return r*f;
}
int main()
{
n=read();
for(int i=1;i<=n;i++)
a[i].v=read(),a[i].id=i;
sort(a+1,a+1+n,cmp);
for(int i=1;i<=n;i++)
f[i]=a[i].id;
for(int i=1;i<=n;i++)
g[i]=max(1ll,mx-i+1),mx=max(mx,f[i]);
g[n+1]=1;
for(int i=1;i<=n;i++)
ans+=max(g[i],g[i+1]);
printf("%lld\n",ans);
return 0;
}