树状数组求逆序对(离散化)

题目描述:

在这个问题中,您必须分析特定的排序算法----超快速排序。
该算法通过交换两个相邻的序列元素来处理 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;
    }
}

在这里插入图片描述
由于离散化的原因,可以看出树状数组还是慢很多的。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值