您的位置:首页 > 其它

HDOJ 题目2838 Cow Sorting(树状数组逆序对)

2014-11-17 17:16 483 查看


Cow Sorting

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 2417    Accepted Submission(s): 776


Problem Description

Sherlock's N (1 ≤ N ≤ 100,000) cows are lined up to be milked in the evening. Each cow has a unique "grumpiness" level in the range 1...100,000. Since grumpy cows are more likely to damage Sherlock's milking equipment, Sherlock would like to reorder the cows
in line so they are lined up in increasing order of grumpiness. During this process, the places of any two cows (necessarily adjacent) can be interchanged. Since grumpy cows are harder to move, it takes Sherlock a total of X + Y units of time to exchange two
cows whose grumpiness levels are X and Y.

Please help Sherlock calculate the minimal time required to reorder the cows.

 

Input

Line 1: A single integer: N

Lines 2..N + 1: Each line contains a single integer: line i + 1 describes the grumpiness of cow i.

 

Output

Line 1: A single line with the minimal time required to reorder the cows in increasing order of grumpiness.

 

Sample Input

3
2
3
1

 

Sample Output

7

Hint
Input Details

Three cows are standing in line with respective grumpiness levels 2, 3, and 1.
Output Details

2 3 1 : Initial order.
2 1 3 : After interchanging cows with grumpiness 3 and 1 (time=1+3=4).
1 2 3 : After interchanging cows with grumpiness 1 and 2 (time=2+1=3).

 

Source

2009 Multi-University Training Contest 3 - Host
by WHU

 

Recommend

gaojie   |   We have carefully selected several similar problems for you:  3450 2227 3030 2642 2836 

分析:其实这个结果和逆序数有关,对某个位置i,如果前面比他大的有x个,那么a[i]至少要加x次 
如果后面有y个比a[i]小,那么a[i]至少要加y次,也就是说用两个树状数组来分别维护当前位置时前面有多少比他大,后面有多少个比他小

ac代码

 
#include<stdio.h>
#include<string.h>
__int64 a[100010],b[100010],num[100010],n;
__int64 low(__int64 x)
{
return x&(-x);
}
void add(__int64 *a,__int64 p,__int64 q)
{
while(p<=n)
{
a[p]+=q;
p+=low(p);
}
}
__int64 sum(__int64 *a,__int64 p)
{
__int64 ans=0;
while(p>0)
{
ans+=a[p];
p-=low(p);
}
return ans;
}
int main()
{
//int n;
while(scanf("%d",&n)!=EOF)
{
int i;
__int64 ans=0;
for(i=1;i<=n;i++)//计算前边比当前位小的数
{
scanf("%d",&num[i]);
add(a,num[i],1);
ans+=num[i]*(i-sum(a,num[i]));
}
for(i=n;i>0;i--)//计算后边比当前大的数
{
ans+=num[i]*sum(b,num[i]-1);
add(b,num[i],1);
}
printf("%I64d\n",ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: