标签:
题意:给出n个数,每次可以把第一个数挪到最后一个位置去,问这n种排列里面的最小逆序对数
先把最开始的逆序对数求出来
然后对于一个数a[i],比它小的数有a[i] - 1个,比它大的数有n - a[i]个
所以把a[i]挪到数列的最末尾的时候, 相当于损失了a[i] - 1个逆序数,得到了n - a[i] 个逆序数
即为共得到n - 2*a[i] + 1个
再做n次比较,维护一个最小值
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include <cmath> 5 #include<stack> 6 #include<vector> 7 #include<map> 8 #include<set> 9 #include<queue> 10 #include<algorithm> 11 using namespace std; 12 13 typedef long long LL; 14 const int INF = (1<<30)-1; 15 const int mod=1000000007; 16 const int maxn=50005; 17 18 int n; 19 int a[maxn],c[maxn]; 20 21 int lowbit(int x){ return x &(-x);} 22 23 int sum(int x){ 24 int ret =0; 25 while(x>0){ 26 ret+=c[x];x-=lowbit(x); 27 } 28 return ret; 29 } 30 31 void add(int x,int d){ 32 while(x<=n){ 33 c[x]+=d;x+=lowbit(x); 34 } 35 } 36 37 int main(){ 38 while(scanf("%d",&n) != EOF){ 39 memset(c,0,sizeof(c)); 40 for(int i=1;i<=n;i++) scanf("%d",&a[i]),a[i]++; 41 42 int ans=0; 43 for(int i=1;i<=n;i++){ 44 ans += i - 1-sum(a[i]); 45 // printf("ans=%d\n",ans); 46 add(a[i],1); 47 } 48 int minn=INF; 49 for(int i=1;i<=n;i++){ 50 ans += n-2*a[i] + 1; 51 minn=min(minn,ans); 52 } 53 printf("%d\n",minn); 54 } 55 return 0; 56 }
HDU 1394 Minimum Inversion Number【 树状数组 】
标签:
原文地址:http://www.cnblogs.com/wuyuewoniu/p/4613086.html