题目描述:
在这个问题中,您必须分析特定的排序算法----超快速排序。
该算法通过交换两个相邻的序列元素来处理 n 个不同整数的序列,直到序列按升序排序。
对于输入序列 9 1 0 5 4,超快速排序生成输出 0 1 4 5 9。
您的任务是确定超快速排序需要执行多少交换操作才能对给定的输入序列进行排序。
输入格式
输入包括一些测试用例。
每个测试用例的第一行输入整数 n,代表该用例中输入序列的长度。
接下来 n 行每行输入一个整数 ai,代表用例中输入序列的具体数据,第 i 行的数据代表序列中第 i 个数。
当输入用例中包含的输入序列长度为 0 时,输入终止,该序列无需处理。
输出格式
对于每个需要处理的输入序列,输出一个整数 op,代表对给定输入序列进行排序所需的最小交换操作数,每个整数占一行。
数据范围
0≤N<500000,
0≤ai≤999999999
输入样例:
5
9 1 0 5 4
3
1 2 3
0
输出样例:
6
0
离散化树状数组:
#include<iostream>
#include<cstring>
#include<algorithm>
#define endl "\n"
using namespace std;
typedef long long ll;
const int N=5e5+7;
int tree[N],n;
struct xy{
int id,s;
inline bool operator <(const xy &a){
return s<a.s;
}
}S[N];
int lowit(const int &x){
return x&-x;
}
void insert(int x){
for(;x<N;x+=lowit(x)) ++tree[x];
}
int sum(int x){
int res=0;
for(;x;x-=lowit(x)) res+=tree[x];
return res;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
while(cin>>n){
if(n==0)return 0;
memset(tree,0,sizeof(tree));
ll ans=0;
for(int i=1;i<=n;i++){
cin>>S[i].s;
S[i].id=i;
}
sort(S+1,S+n+1);
for(int i=1;i<=n;i++){
ans+=i-1-sum(S[i].id);
insert(S[i].id);
}
cout<<ans<<endl;
}
}
归并排序:
#include<iostream>
#include<cstring>
using namespace std;
const int N=5e5+7;
int s[N];
int t[N];
long long sum=0;
void tree(int l,int f){
int cnt=(l+f)>>1,i,j,cc;
if(l<f){
tree(l,cnt);
tree(cnt+1,f);
for(i=l,j=cnt+1,cc=l;i<=cnt&&j<=f;)
if(s[i]<=s[j]){
t[cc++]=s[i];
i++;
}
else if(s[i]>s[j])
{
t[cc++]=s[j];
sum+=cnt-i+1;
j++;
}
for(;i<=cnt;i++)
t[cc++]=s[i];
for(;j<=f;j++)
t[cc++]=s[j];
for(int i=l;i<=f;i++)
s[i]=t[i];
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
while(cin>>n){
if(n==0)return 0;
sum=0;
memset(s,0,sizeof(s));
memset(t,0,sizeof(t));
for(int i=1;i<=n;i++)
cin>>s[i];
tree(1,n);
cout<<sum<<endl;
}
}
由于离散化的原因,可以看出树状数组还是慢很多的。