HDU2689 Sort it【树状数组】【逆序数】

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=2689


题目大意:

求把一个具有N个不同元素的序列通过交换两个相邻的元素转换成升序序列需要进行的交换次数

是多少。

例如:1 2 3 5 4,只需要交换5和4,交换次数为1次。


思路:

典型的求逆序数题。其实可以直接暴力过。但是用树状数组效率比较高。对于值为a第i个元素,

需要交换次数为前i个元素中大于a的元素个数,即逆序数。

用树状数组来做,数组Tree[i]表示数字i是否在序列中出现过,如果数字i已经存在于序列中,

Tree[i] = 1,否则Tree[i] = 0。按序列从左到右将值为a的元素当作下标为a,赋值为1插入树状

数组里,这时,比a的数个数就是i - Query(a)。将全部结果累加起来就是逆序数了。


AC代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN = 100010;

int N,Tree[MAXN];

int Lowbit(int i)
{
    return i & (-i);
}

void Update(int i,int x)
{
    while(i <= N)
    {
        Tree[i] = Tree[i] + x;
        i = i + Lowbit(i);
    }
}

int Query(int n)
{
    int sum = 0;
    while(n > 0)
    {
        sum += Tree[n];
        n = n - Lowbit(n);
    }
    return sum;
}

int main()
{
    while(cin >> N && N)
    {
        int a,ans = 0;
        memset(Tree,0,sizeof(Tree));
        for(int i = 1; i <= N; ++i)
        {
            cin >> a;
            Update(a,1);
            ans += i - Query(a);
        }
        cout << ans << endl;
    }

    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值