hdu2838Cow Sorting(树状数组+逆序数)

来源:互联网 发布:mysql oracle 区别 编辑:程序博客网 时间:2024/05/22 00:05

题目链接:点击打开链接

题意描述:给定一个长度为100000的数组,每个元素范围在1~100000,且互不相同,交换其中的任意两个数需要花费的代价为两个数之和。问如何交换使数组有序,花费的代价最小?

解题思路:

1、显然我们知道,要使一个数组有序至少交换的次数(即必须要交换的次数)为数组中的逆序数

2、由于数组的长度比较大所以我们可以通过树状数组来统计结果

此处需要两个树状数组

第一个:记录小于等于某个值的元素的个数

第二个:记录小于等于某个值的元素的和


代码:

#include <cstdio>#include <cstring>#define MAXN 100010using namespace std;int C[MAXN];int lowbit(int x){    return x&(-x);}int sum(int pos){    int ret=0;    while(pos>0)    {        ret+=C[pos];        pos-=lowbit(pos);    }    return ret;}void add(int pos,int v){    while(pos<=100000)    {        C[pos]+=v;        pos+=lowbit(pos);    }}long long Ct[MAXN];long long sumt(int pos){    long long ret=0;    while(pos>0)    {        ret+=Ct[pos];        pos-=lowbit(pos);    }    return ret;}void addt(int pos,int v){    while(pos<=100000)    {        Ct[pos]+=v;        pos+=lowbit(pos);    }}int main(){    int n;    while(scanf("%d",&n)!=EOF)    {        memset(C,0,sizeof(C));        memset(Ct,0,sizeof(Ct));        long long ans=0;        int x;        for(int i=0; i<n; ++i)        {            scanf("%d",&x);            add(x,1);            addt(x,x);            ans+=((sum(100000)-sum(x))*(long long)x+sumt(100000)-sumt(x));///注意溢出问题        }        printf("%I64d\n",ans);    }    return 0;}



1 0
原创粉丝点击