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;
}