HDU-1394-Minimum Inversion Number
Http://acm.hdu.edu.cn/showproblem.php? Pid = 1, 1394
The meaning is to give n numbers, calculate their reverse order number, and move the first number to the end each time, then calculate its reverse order number, and find the smallest reverse order number in the n orders
A simple definition of The number of reverse orders: The inversion number of a givennumber sequence a1, a2 ,..., an is the number of pairs (ai, aj) that satisfy I <j and ai> aj.
Assume that we have obtained an array with the reverse order of sum and the array is a [n]. Now we move the first number to the end, because the numbers 0 to n-1 are continuous, a number larger than a [0] will become a reverse order, and a number smaller than a [0] will not constitute a reverse order, so the number of reverse orders is sum + = (a number larger than a [0]-a number smaller than a [0)
That is sum + = (n-1-a [0]-a [0]) That is sum + = (n-1-2 * a [0])
In this case, the number of reverse orders in the original arrangement can be brute force, that is, each number is compared with the previous number.
#include<stdio.h>#include<string.h>#include<stdlib.h>int main(){int n,sum,i,j,ans;int a[5005];while(scanf("%d",&n)!=EOF){for(i=0;i<n;i++)scanf("%d",&a[i]);sum=0;for(i=0;i<n;i++)for(j=0;j<i;j++)if(a[j]>a[i])sum++;ans=sum;for(i=0;i<n;i++){sum+=(n-1-2*a[i]);if(sum<ans)ans=sum;}printf("%d\n",ans);}return 0;}
The brute-force method is time-consuming to find the number of reverse orders in the original arrangement. This question can also be done using the line segment tree.
1 3 6 9 0 8 5 7 4 2
Insert in sequence. When insert 1, v1 = 0 appears in (1, n-1 ].
When inserting 3, v2 = 0 appears in (3, n-1]
...
When 0 is inserted, v5 = 4 appears in (0, n-1]
...
Add v1 to v10.
# Include <stdio. h> # include <string. h> # include <stdlib. h> # define N 5005int a [N]; struct cam {int x; // start point int y; // end point int val;} list [N * 4]; void build (int k, int x, int y) // build {int mid; list [k]. x = x; list [k]. y = y; list [k]. val = 0; if (list [k]. x = list [k]. y) return; mid = (x + y)/2; build (k <1, x, mid); build (k <1 | 1, mid + 1, y);} int find (int k, int x, int y) // The number {int mid that is larger than x in (x, y; if (list [k]. x = x & list [k]. y = y) return list [k]. val; mid = (List [k]. x + list [k]. y)/2; if (x> mid) return find (k <1 | 1, x, y); else if (y <= mid) return find (k <1, x, y); elsereturn find (k <1, x, mid) + find (k <1 | 1, mid + 1, y);} void update (int x, int k) // update the val values of all intervals containing x {int mid; list [k]. val ++; if (list [k]. x = list [k]. y) return; mid = (list [k]. x + list [k]. y)/2; if (x <= mid) update (x, k <1); elseupdate (x, k <1 | 1);} int main () {int I, n, sum, ans; while (scanf ("% d", & n )! = EOF) {build (, n-1); sum = 0; for (I = 0; I <n; I ++) {scanf ("% d ", & a [I]); sum + = find (1, a [I], n-1); update (a [I], 1) ;}ans = sum; for (I = 0; I <n; I ++) {sum + = (n-1-2 * a [I]); if (sum <ans) ans = sum ;} printf ("% d \ n", ans);} return 0 ;}