HDU1394-Minimum Inversion Number
http://acm.hdu.edu.cn/showproblem.php?pid=1394
Minimum Inversion Number
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 8205 Accepted Submission(s): 5041
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
#include<stdio.h> #define maxn 500004 struct node { int left,right; int sum; }; int val[maxn]; int n; node tree[3*maxn]; void build(int left,int right,int i) { tree[i].left =left; tree[i].right =right; tree[i].sum =0; if(tree[i].left ==tree[i].right ) return ; build(left,(left+right)/2,2*i); build((left+right)/2+1,right,2*i+1); } void update(int r,int j) { tree[r].sum++; if(tree[r].left==tree[r].right) return ; int mid=(tree[r].left +tree[r].right )/2; if(j<=mid) update(r*2,j); if(j>mid) update(r*2+1,j); } int getsum(int p, int left, int right) { if (left > right) return 0; if (tree[p].left == left && tree[p].right == right) return tree[p].sum; int m = (tree[p].left + tree[p].right) / 2; if (right <= m) return getsum(p*2, left, right); else if (left > m) return getsum(p*2+1, left, right); else return getsum(p*2, left, m) + getsum(p*2+1, m + 1, right); } int main() { while (~scanf("%d",&n)) { build(0,n - 1,1); int i,sum =0,ans; for (i = 1;i<= n; i++) { scanf("%d", &val[i]); sum += getsum(1, val[i], n - 1); update(1, val[i]); } ans = sum; for (i = 1; i <= n; i++) { sum = sum + (n - val[i] - 1) - val[i]; ans = sum < ans ? sum : ans; } printf("%d\n", ans); } return 0; }