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

HDU - 2838

Cow Sorting

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

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

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

时间: 2024-10-27 18:11:54

HDU - 2838 Cow Sorting (树状数组 + 逆序对)的相关文章

hdu 2838 Cow Sorting 树状数组求所有比x小的数的个数

Cow Sorting Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 4766    Accepted Submission(s): 1727 Problem Description Sherlock's N (1 ≤ N ≤ 100,000) cows are lined up to be milked in the evening.

hdu 2838 Cow Sorting 树状数组

hdu2838 ------希望30号驾校科目一顺利考完,4月即将过去说好的30篇博客也没完成, 真是忙起来就会烦躁什么都不想做,勿忘心安.... <Cow Sorting> 这题本来兴高采烈的想用java做一遍,结果做出来之后无限超内存,真是啊,做题的时候java这种东西还是轻易不要动了.还有感觉要把数字都要离散化的,结果后台数据不需要离散化. 题意:给一个n代表n个牛,然后再给n个数我觉得是n以内的数(包括n).虽然体面上没说.然后只能相邻两个数字交换位置,会让牛产生怒气值,值为互相移动的

hdu 2838 coew sorting(树状数组)

求逆序对的和 分析:其实这个结果和逆序数有关,对某个位置i,如果前面比他大的有x个,那么a[i]至少要加x次 如果后面有y个比a[i]小,那么a[i]至少要加y次,也就是说用两个树状数组来分别维护当前位置时前面有多少比他大,后面有多少个比他小 如求逆序数两两的总和: 如 3 2 1 :sum=(3+2)+(3+1)+(2+1)=12;   1 2 3: sum=0; 对于新插入的一个元素,运用树状数组,可以求得比它小的元素的个数,比它小的元素的和,在它之前的元素的总和. 而对于每一个新元素,其s

HDU Cow Sorting (树状数组)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2838 Cow Sorting 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 cow

hdu 5193 分块 树状数组 逆序对

题意: 给出n个数,a1,a2,a3,...,an,给出m个修改,每个修改往数组的某个位置后面插入一个数,或者把某个位置上的数移除.求每次修改后逆序对的个数. 限制: 1 <= n,m <= 20000; 1 <= ai <= n 思路: 插入和删除用分块来处理,块与块之间用双向链表来维护,每一块用树状数组来求小于某个数的数有多少个. 外层可以使用分块维护下标,这样添加和删除元素的时候,也很方便,直接暴力.查找权值个数时,使用树状数组比较方便.内层通过树状数组维护权值. 每次更新即

HDU 2689Sort it 树状数组 逆序对

Sort it Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 4110    Accepted Submission(s): 2920 Problem Description You want to processe a sequence of n distinct integers by swapping two adjacent s

Poj 2299 - Ultra-QuickSort 离散化,树状数组,逆序对

Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 52306   Accepted: 19194 Description In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by swappin

HDU 1394Minimum Inversion Number 数状数组 逆序对数量和

Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 18543    Accepted Submission(s): 11246 Problem Description The inversion number of a given number sequence a1, a2, ..., a

Bzoj 2789: [Poi2012]Letters 树状数组,逆序对

2789: [Poi2012]Letters Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 278  Solved: 185[Submit][Status][Discuss] Description 给出两个长度相同且由大写英文字母组成的字符串A.B,保证A和B中每种字母出现的次数相同. 现在每次可以交换A中相邻两个字符,求最少需要交换多少次可以使得A变成B. Input 第一行一个正整数n (2<=n<=1,000,000),表示字符串的长度