您的位置:首页 > 其它

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

2015-04-28 17:05 190 查看
题目链接:

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
.Cnt;
n -= Lowbit(n);
}
return ans;
}

LL QuerySum(int n) //返回值为a的数前边比a小的元素的和
{
LL ans = 0;
while(n > 0)
{
ans += Tree
.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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: