HDU_2838_Cow Sorting_树状数组

来源:互联网 发布:java毫秒数转时间 在线 编辑:程序博客网 时间:2024/06/11 15:19
题目大意
若干头牛,每头牛有一个权值,通过相邻交换将牛按权值升序排列,每次交换以两头牛的权值之和为代价,求最小代价。
思路
原排列确定后,每个数的与其之前的数形成的逆序对是固定的,(此类最小交换次数问题考虑逆序数)每次仅考虑一个数之前与其形成的逆序对避免重复计算,每次通过树状数组计算一次逆序对数(a)和次数前与其形成逆序的数之和(s),维护两个树状数组,没次代价为x * a + s
#include <iostream>#include <cstdio>#include <string.h>#define MAXN 100010using namespace std;int a[MAXN], n, upper = 0;long long sum[2][MAXN];int lowbit(int x){    return x & (-x);}void update(int num, int i, int val){    while (i <= upper)    {        sum[num][i] += val;        i += lowbit(i);    }}long long getSum(int num, int i){    long long s = 0;    while (i > 0)    {        s += sum[num][i];        i -= lowbit(i);    }    return s;}int main(){    //freopen("aa.txt", "r", stdin);    long long result = 0, tol = 0;    memset(sum, 0, sizeof(sum));    scanf("%d", &n);    for (int i = 1; i <= n; i++)    {        scanf("%d", &a[i]);        if (a[i] > upper)            upper = a[i];    }    for (int i = 1; i <= n; i++)    {        long long temp = getSum(0, a[i]);        long long temp1 = getSum(1, a[i]);        result += (long long)(a[i] * (i - 1 - temp) + tol - temp1);        tol += a[i];        update(1, a[i], a[i]);        update(0, a[i], 1);    }    cout << result << endl;}

原创粉丝点击