HDU 1394 - Minimum Inversion Number
Problem Description
The inversion number of a given number sequence a1, a2, ..., an is the number of pairs (ai, aj) that satisfy i < j and ai > aj.
For a given sequence of numbers a1, a2, ..., an, if we move the first m >= 0 numbers to the end of the seqence, we will obtain another sequence. There are totally n such sequences as the following:
a1, a2, ..., an-1, an (where m = 0 - the initial seqence)
a2, a3, ..., an, a1 (where m = 1)
a3, a4, ..., an, a1, a2 (where m = 2)
...
an, a1, a2, ..., an-1 (where m = n-1)
You are asked to write a program to find the minimum inversion number out of the above sequences.
For a given sequence of numbers a1, a2, ..., an, if we move the first m >= 0 numbers to the end of the seqence, we will obtain another sequence. There are totally n such sequences as the following:
a1, a2, ..., an-1, an (where m = 0 - the initial seqence)
a2, a3, ..., an, a1 (where m = 1)
a3, a4, ..., an, a1, a2 (where m = 2)
...
an, a1, a2, ..., an-1 (where m = n-1)
You are asked to write a program to find the minimum inversion number out of the above sequences.
Input
The input consists of a number of test cases. Each case consists of two lines: the first line contains a positive integer n (n <= 5000); the next line contains a permutation of the n integers from 0 to n-1.
Output
For each case, output the minimum inversion number on a single line.
Sample Input
10
1 3 6 9 0 8 5 7 4 2
Sample Output
16
大致题意:
一个由0..n-1组成的序列,每次可以把队首的元素移到队尾;
求形成的n个序列中最小逆序对数目;
求形成的n个序列中最小逆序对数目;
解题思路:
以下有两份代码:
代码一:
暴力法,复杂度 O(n^2);
当吧 a[0] 移到队尾后,会减少 a[0] 个逆序对 同时会增加 (n-1)-a[0] 个逆序对;
那么只要求出初始的逆序对数好了,剩下的可以推导得出;
代码二:
树状数组,复杂度0(nlogn);
无非就是用树状数组求逆序对,注意数列从0开始的,要处理过;
剩下的还是找规律;
1 #include <cstdio> 2 using namespace std; 3 int main(){ 4 int n,a[5000+5],t; 5 while(~scanf("%d",&n)){ 6 for(int i=0;i<n;i++) scanf("%d",&a[i]); 7 t=0; 8 for(int i=0;i<n;i++) 9 for(int j=i+1;j<n;j++) 10 if(a[i]>a[j]) t++; 11 int min=t; 12 for(int i=0;i<n;i++){ 13 t=t-a[i]+(n-1)-a[i]; 14 if(t<min) min=t; 15 } 16 printf("%d\n",min); 17 } 18 }
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 #define N 5005 6 int c[N],a[N],n,m; 7 int modify(int x,int num){while(x<=n)c[x]+=num,x+=x&-x;} 8 int sum(int x){int s=0;while(x>0)s+=c[x],x-=x&-x;return s;} 9 int main(){ 10 while(~scanf("%d",&n)){ 11 memset(c,0,sizeof(c)); 12 m=0; 13 for(int i=0;i<n;i++){ 14 scanf("%d",&a[i]); 15 a[i]+=1;//0->n-1 >>> 1->n 16 modify(a[i],1); 17 m+=i+1-sum(a[i]);//0->n-1 >>> 1->n 18 } int ans=m; 19 for(int i=0;i<n;i++){ 20 a[i]-=1;//变回来 21 ans=min(ans,m=m-a[i]+n-1-a[i]); 22 } printf("%d\n",ans); 23 } return 0; 24 }
我自倾杯,君且随意