数据结构 H 逆序的人生

逆序的人生

给定一个n个元素的数组,这个数组由1…n的一个排列,输出其逆序对数。

输入:正整数n,然后输入n个元素(n<=100000

输出:一行,表示其逆序数(int范围内)。

样例输入:

4 3 1 5 2

样例输出:

6


开始傻傻地想要暴力。。。。犯糊涂了。。。肯定超时的。

用树状数组的话可以减少复杂度,直接套用模板,便可以得出。

关键部分:ans += a[i]-query(a[i]);     //这里是关键,query(a[i])此时返回的结果是将a[i]在这个状态下比a[i]小的个数(包括a[i]),很明显我们是按照从前往后的先后顺序插入的,那么这个值就求的了他前面比它小的数,包括他自己,那么用它自己减去这个值就得到了后面比它小的个数了。。。

#include <iostream>
#include <stdio.h>
#include <memory.h>
using namespace std;
const int maxn=100010;
int n,a[maxn],in[maxn];
int lowbit(int t)
{
    return t&(-t);
}
void modify(int pos,int num)
{
    while(pos<=n)
    {
        in[pos]+=num;
        pos+=lowbit(pos);
    }
}
int query(int end)
{
    int sum=0;
    while(end>0)
    {
        sum+=in[end];
        end-=lowbit(end);
    }
    return sum;
}
int main()
{
    int i,j,k,l,q,ans;
    while(scanf("%d",&n)!=EOF)
    {
        for(i=1;i<=n;i++)
        in[i]=0;
        ans=0;
        for(i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            modify(a[i],1);
            ans+=a[i]-query(a[i]);
        }
        printf("%d\n",ans);
    }
    return 0;

}



评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值