Hdu 2838 step5.3.7
Cow Sorting
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2081 Accepted Submission(s): 642
Problem Description
Sherlock's N (1 ≤ N ≤ 100,000) cows are lined up to be milked in the evening. Each cowhas a unique "grumpiness" level in the range 1...100,000. Sincegrumpy cows are more likely to damage Sherlock's milking equipment, Sherlockwould like to reorder the cows in line so they are lined up in increasing orderof grumpiness. During this process, the places of any two cows (necessarilyadjacent) can be interchanged. Since grumpy cows are harder to move, it takesSherlock a total of X + Y units of time to exchange two cows whose grumpinesslevels are X and Y.
Please help Sherlock calculate the minimaltime required to reorder the cows.
Input
Line 1: A single integer: N
Lines 2..N + 1: Each line contains a singleinteger: line i + 1 describes the grumpiness of cow i.
Output
Line 1: A single line with the minimal timerequired 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 withrespective grumpiness levels 2, 3, and 1.
Output Details
2 3 1 : Initial order.
2 1 3 : After interchanging cows withgrumpiness 3 and 1 (time=1+3=4).
1 2 3 : After interchanging cows withgrumpiness 1 and 2 (time=2+1=3).
Source
2009 Multi-University Training Contest 3 -Host by WHU
题解:
这道题用的是树状数组,因为是算相邻牛交换,然后达到不递减的效果,每次的代价是两只牛的暴力值相加,。根据题意,可知我们要算的是,在当前牛cows前面有多少暴力值比它大的牛。交换当前牛的代价是到当前牛的总暴力值ssum,减去顺序暴力值的总和sum,在加上逆序暴力牛的只数*当前牛的暴力值(len2-len1)*cows。即ans += ssum – sum + (len2-len1)*cows。而计算sum的值就可以用树状数组——将当前牛的暴力值加入到树状数组中add(cows,cows),不排除有相等的暴力值,所以要记录重复暴力值的个数,用dc[cows]记录,而计算到当前这个暴力值,比它小的牛的暴力值的总和,用getsum(cows),然后计算出有多少个比当前牛小或者相等的值,len2 += dc[x];因为这道题的值是比较大的,所以要用__int64,而且最后在计算ans的时候所有的值都要转换为__int64来计算,不然会出错。
源代码:
#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;
#define MAX 100050
int cows,len1,len2;
__int64 c[100050];
int dc[100050];
int lowbit(int x)
{
returnx&(-x);
}
void add(int x,int num)
{
while(x> 0 && x < MAX)
{
c[x] += num;
dc[x]++;
x += lowbit(x);
}
}
__int64 getsum(int x)
{
__int64sum = 0;
while(x> 0 && x < MAX)
{
sum += c[x];
len2 += dc[x];
x -= lowbit(x);
}
returnsum;
}
int main()
{
intn;
__int64ans,ssum,sum;
while(scanf("%d",&n)!=EOF)
{
ans = 0;
ssum = 0;
memset(c,0,sizeof(c));
memset(dc,0,sizeof(dc));
for(int i = 0;i < n;i++)
{
scanf("%d",&cows);
add(cows,cows);
ssum += (__int64)cows;
len1 = i+1;
len2 = 0;
sum = getsum(cows);
ans += ssum - sum +(len1-len2)*(__int64)cows;
}
printf("%I64d\n",ans);
}
return0;
}