HDU - Cow Sorting (树状数组)

Cow Sorting

题目链接: Cow Sorting

题意

给定一个大小为N的数组,数组为1~N的全排列,为使数组形成单调递增,需多次交换相邻的两个数,设Cost为交换x,y时的x+y。求最小Cost。


思路

首先,我们看到了逆序对,这样想到的肯定时树状数组了,树状数组可是解决逆序对的好手。

这里还有一个问题,就每次交换都需要消耗,如果是普通的逆序对显然不行,因为通常做的时候我们只关注一个数字,然后通过O(logn)的复杂度来得到比他要大的数据量。

因为只关注一个数字,我们无法按照题目思路的来直接求 x+y ,在仔细思考后,我觉得不止要得到有多少数据在他左边并且大于他,还应该关注有多少数据在他右边并且小于他。这样的次数就是他的总交换次数。


代码

#include 
using namespace std;
#define rep(i,j,k) for(int i = (int)j;i <= (int)k;i ++)
#define per(i,j,k) for(int i = (int)j;i >= (int)k;i --)
#define mmm(a,b) memset(a,b,sizeof(a))
#define pb push_back
#define mp make_pair

typedef double db;
typedef long long ll;
const int MAXN = (int)1e6+7;
const int INF = (int)0x3f3f3f3f;

int N;
int c[MAXN];
int A[MAXN];

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

int getSum(int l) {
    int sum = 0;
    while (l > 0) {
        sum += c[l];
        l -= lowbit(l);
    }
    return sum;
}

void Update(int l,int val) {
    while (l <= N){
        c[l] += val;
        l += lowbit(l);
    }
}

int main()
{
    scanf("%d",&N);
    rep(i,1,N) scanf("%d",&A[i]);

    ll ans = 0;
    rep(i,1,N) {
        Update(A[i],1);
        ans += (ll)(A[i] - getSum(A[i]))*(ll)(A[i]);     //有多少小于他,并且在他右边的
        ans += (ll)(getSum(N) - getSum(A[i]))*(ll)(A[i]);//有多少大于他,并且在他左边的
    }
    printf("%lld\n",ans);
}

你可能感兴趣的:(线段树,树状数组,莫队)