HDU 2838 (树状数组求逆序数)

来源:互联网 发布:特效视频制作软件 编辑:程序博客网 时间:2024/06/05 16:08


题意:

给你N个排列不规则的数(1~N),任务是把它从小到大排好,每次只能交换相邻两个数,交换一次的代价为两数之和,求最小代价



思路:对于当前数X,我们如果知道前面比它大的数有多少,假设为K,那么有部分代价是确定的,那就是K*X;然后还得加上比它大的那些数之和,这就是当数列到X为止,排好所需要的最小代价。



#include <stdio.h>  #include <iostream>  #include <algorithm>  #include <string.h>  #include <math.h>  #define M 100005  #define LL __int64  using namespace std;   struct node{LL sum;int id;}c[M];int n;  int Lowbit(int x)  {      return x&(-x);  }    void Update(int x,int k,int num)  {      while(x<=n)      {          c[x].id +=k;c[x].sum +=num;        x+=Lowbit(x);      }  }    LL getSum(int x)  {      LL sum=0;      while(x>0)      {          sum+=c[x].sum;          x-=Lowbit(x);      }      return sum;  }    int getNum(int x)  {  int sum=0;      while(x>0)      {          sum+=c[x].id;          x-=Lowbit(x);      }      return sum;  }  int main()  {      while(~scanf("%d",&n))     {  int x;        memset(c,0,sizeof(c));LL ans=0,k;for(int i=1;i<=n;i++){scanf("%d",&x);            Update(x,1,x);              LL k=(i-getNum(x));  if(k==0)continue;ans+=(k*x+getSum(n)-getSum(x));        }          printf("%I64d\n",ans);      }      return 0;  }  /*4324117*/


0 0