Minimum inversion number
Time limit:2000/1000 MS (java/others) Memory limit:65536/32768 K (java/others)
Total submission (s): 4904 Accepted Submission (s): 2991
Problem Description the inversion number of a given number sequence A1, A2, ..., the number of pairs (AI, AJ) that s Atisfy 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'll Obtain another sequence. There is 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 is 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 the 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 in a single line.
Sample Input
10 1 3 6 9 0 8 5 7 4 2
Sample Output
16
Author CHEN, Gaoli
Source ZOJ Monthly, January 2003
Recommend IGNATIUS.L
First of all, the idea of reverse number pairs: 1. After the entire series, the previous sweep, statistics than a[i] small, in the a[i] behind the number of such things, should be only N2 violence, did not think of a better method 2. Statistics A[i] in front of, and larger than the number of it to do so, You can use the input timeliness, each input a number, the number of the Num[i] value plus 1, and then statistics than this number of num number and, because here and must be in this series than a[i], and the sum of the number that appears in front of it, and then put this and add to the total reverse number sum. In doing so, the direct violence is still N2, but we can optimize the number of NUM and this step in statistics, the complexity of using segment tree to find the value of interval domain is LOGN, so the overall complexity is reduced to NLOGN.
Look at this problem again, after the initial sequence of the reverse number, and then the other permutation of the number of reverse order has a rule, that is, sum = sum + (n-1-a[i])-a[i]; This is self-validating, I believe it's easy to come up
Finally, expand, if the requirements of the positive ordinal what to do. Very simple, is nothing more than the size of the tune to ask, if the requirements meet i<j<k, and A[i]>a[j]>a[k] The number of total what to do.
Can start from this number, statistics a[i]>a[j] logarithmic m, and A[j]>a[k] logarithmic n,m*n is ... Ask A[i]>a[j] The number is the same, then the number of a[j]>a[k]. Two ideas: 1. After obtaining the logarithm of a[i]>a[j], the logarithm of the series is reversed and then A[j]<a[k] is 2. It is simpler to find a rule finding that n = the number of smaller numbers in the entire sequence than a[j], which is smaller than a[j before A[j] i.e. (assuming that the sequence is starting from 1) n = (A[j]-1)-(J-1-M)
This problem code
#include <stdio.h> #include <algorithm> using namespace std;
int a[5005]; struct node{int l,r,num;}
TREE[50000];
void Build (int n,int x,int y) {tree[n].l = x;
TREE[N].R = y;
Tree[n].num = 0;
if (x = = y) {return;
} int mid = (x + y)/2;
Build (2*n,x,mid);
Build (2*n+1,mid+1,y);
} void Modify (int n,int x) {int l = TREE[N].L;
int r = TREE[N].R;
int mid = (L + r)/2;
if (x = = L && x = = r) {tree[n].num = 1;
Return
} if (x <= mid) Modify (2*N,X);
else Modify (2*n+1,x);
Tree[n].num = Tree[2*n].num + tree[2*n+1].num;
} int Query (int n,int x,int y) {int l = TREE[N].L;
int r = TREE[N].R;
int mid = (L + r)/2;
int ans = 0;;
if (x = = L && y = = r) return tree[n].num;
if (x <= mid) ans + = Query (2*n,x,min (mid,y));
if (Y > Mid) ans + = Query (2*n+1,max (mid+1,x), y);
return ans;
} int main () {int n,sum,ans; int I, J;
while (scanf ("%d", &n)! = EOF) {sum = 0;
Build (1,0,n);
for (i = 1;i <= n;i++) {scanf ("%d", &a[i]);
Modify (1,a[i]);
Sum + = Query (1,a[i]+1,n);
} ans = sum;
for (i = 1;i < n;i++) {sum = sum + (n-1-a[i])-a[i];
if (sum < ans) ans = sum;
} printf ("%d\n", ans);
}
}