码迷,mamicode.com
首页 > 编程语言 > 详细

HDU2838 Cow Sorting【树状数组】【逆序数】

时间:2015-04-28 18:28:03      阅读:163      评论:0      收藏:0      [点我收藏+]

标签:

题目链接:

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


题目大意:

有N头奶牛排成一排。每头奶牛都有一个唯一的"坏脾气"值。坏脾气的范围为1~100000。现在将

奶牛重新排序,使奶牛按照坏脾气增加的顺序排列。所有的奶牛都可以相互交换位置。但是交换脾

气值为X,Y的两头奶牛,需要的时间是X+Y。现在问:将奶牛重新排列需要的最短时间是多少。


思路:

这道题就是给你一个N个元素的序列,求这个序列中所有逆序数的和。所以,对于值为a的第i个元素,

除了知道前i个元素里比a大的元素个数之外,还得知道前i个元素里比a大的元素的和。建立结构体树

状数组,一个变量来记录比a小的元素个数,i -比a小的元素个数就是前i个元素里比a大的元素个数(即

逆序数的个数),这样是为了方便计算。另一个变量来记录比a小的元素的和。n个数的和-比a小的元素

和就是之前比a大的数的和。


AC代码:

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

struct Node
{
    int Cnt;    //记录前i个元素里比a大的元素个数
    LL sum;     //记录前i个元素里比a大的元素的和
}Tree[MAXN];

int N;

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

void Update(int i,int v,int Cnt)
{
    while(i <= N)
    {
        Tree[i].sum += v;
        Tree[i].Cnt += Cnt;
        i += Lowbit(i);
    }
}

int QueryCnt(int n) //返回值为a的数前边比a小的元素个数
{
    int ans = 0;
    while(n > 0)
    {
        ans += Tree[n].Cnt;
        n -= Lowbit(n);
    }
    return ans;
}

LL QuerySum(int n)  //返回值为a的数前边比a小的元素的和
{
    LL ans = 0;
    while(n > 0)
    {
        ans += Tree[n].sum;
        n -= Lowbit(n);
    }
    return ans;
}

int main()
{
    int a;
    while(cin >> N)
    {
        LL ans = 0;
        memset(Tree,0,sizeof(Tree));
        for(int i = 1; i <= N; ++i)
        {
            cin >> a;
            Update(a,a,1);
            LL k1 = i - QueryCnt(a);    //k1值为a的第i个元素的逆序对
            if(k1 != 0)
            {
                //值为a的数之前比a大的数的总和
                LL k2 = QuerySum(N) - QuerySum(a);
                ans += k1*a + k2;
            }
        }
        cout << ans << endl;
    }

    return 0;
}


HDU2838 Cow Sorting【树状数组】【逆序数】

标签:

原文地址:http://blog.csdn.net/lianai911/article/details/45338683

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!