码迷,mamicode.com
首页 > 编程语言 > 详细

HDU - 2838 Cow Sorting (树状数组 + 逆序对)

时间:2015-08-10 14:57:55      阅读:197      评论:0      收藏:0      [点我收藏+]

标签:

HDU - 2838
Time Limit: 1000MS   Memory Limit: 32768KB   64bit IO Format: %I64d & %I64u

 Status

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). 
         
 题意:给你一个数组序列,让你排列变成一个递增的排列,每交换相邻的两个数会产生两个数的和的代价,求变成递增的序列后所需的最小代价为多少。
如此,可以推想,对于一个数,他与某些数的交换肯定只能为一次,多了话,代价就会增加,相当于冒泡排序。
而对于冒泡排序,每个数的交换次数等于前面大于它的数的个数加上后面小于它的个数。
如此,如此通过树状数组维护一个前缀以及后缀,来求解比在这个数之前的小于这个数的个数,以及后面少于这个数的个数。
对某个位置i,如果前面比他大的有x个,那么a[i]至少要交换x次 如果后面有y个比a[i]小,那么a[i]至少要交换y次,也就是说用两个树状数组来分别维护当前位置时前面有多少比他大,后面有多少个比他小求解就是结果
技术分享
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
typedef long long LL;
const int MAXN = 1e5 + 5;
int N, A[MAXN], C[MAXN], lv[MAXN], rv[MAXN];

int lowbit(int x) {
    return x & (-x);
}

void add(int x) {
    while(x < MAXN) {
        C[x] += 1;
        x += lowbit(x);
    }
}

int sum(int x) {
    int ret = 0;
    while(x > 0) {
        ret += C[x];
        x -= lowbit(x);
    }
    return ret;
}

int main() {
    while(~ scanf("%d", &N)) {
        memset(C, 0, sizeof(C));
        for(int i = 1 ; i <= N; i ++) {
            scanf("%d", &A[i]);
            add(A[i]);
            lv[i] = sum(A[i] - 1);//左边比A[i]少的数的个数
        }
        memset(C, 0, sizeof(C));
        for(int i = N; i > 0 ; i --) {
            add(A[i]);
            rv[i] = sum(A[i] - 1);//右边比A[i]少的数的个数
        }
        LL ans = 0;
        for(int i = 1; i <= N ; i ++) {
            ans += (LL)(i - 1 - lv[i] + rv[i]) * A[i];//左边的少于他个数加上右边大于他的个数然后乘以他本身可以得到交换的最终代价
        }
        printf("%lld\n", ans);
    }
    return 0;
}



版权声明:本文为博主原创文章,未经博主允许不得转载。

HDU - 2838 Cow Sorting (树状数组 + 逆序对)

标签:

原文地址:http://blog.csdn.net/qq_18661257/article/details/47397237

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!