Minimum inversion number
Time Limit: 2000/1000 MS (Java/others) memory limit: 65536/32768 K (Java/Others)
Total submission (s): 10853 accepted submission (s): 6676
Problem descriptionthe 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.
Inputthe 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.
Outputfor each case, output the minimum inversion number on a single line.
Sample Input
101 3 6 9 0 8 5 7 4 2
Sample output
16
Question and code:
For a typical topic of a line segment tree, use the line segment tree to calculate the number of numbers in reverse order. Here I will explain the idea of program in reverse order.
We use the leaf node of the Line Segment tree to record the existence of the number k in sequence. We start from scanning the number sequence array, each incoming number X, search for its leaf node, mark it as 1, and then update the line segment range. Then, we query the number of lines that are larger than X before X comes in, and use query (x + 1, n, 1.
Next, let's talk about this question. After finding the Reverse Sequence Number of the sequence, record it as sum, then scan from the first element in the sequence, and put it to the end. In this way, we will find that, when we take it out, the reverse order will decrease the X-1, because the number behind X is smaller than X, and when we put it at the end, the number of reverse orders increases by N-X, because there are n-X numbers before X, which are greater than X.
Next, you can write it directly:
# Include <iostream> # include <cstdio> # include <cstdlib> # include <cstring> # include <set> # include <map> # include <queue> # include <string> # define maxn 5010 # define lson l, m, RT <1 # define rson m + 1, R, RT <1 | 1 # define all % i64dusing namespace STD; typedef long ll; struct segment {int l, r; int value;} son [maxn <2]; void pushup (int rt) {son [RT]. value = Son [RT <1]. value + son [RT <1 | 1]. value;} void build (int l, int R, Int RT) {son [RT]. L = L; son [RT]. R = r; son [RT]. value = 0; If (L = r) {// scanf ("% d", & Son [RT]. value); return;} int M = (L + r)/2; build (lson); Build (rson); // pushup (RT );} void update_1 (int p, int value, int RT) {If (son [RT]. L = Son [RT]. r) {son [RT]. value = value; return;} int M = (son [RT]. L + son [RT]. r)/2; If (P <= m) update_1 (p, value, RT <1); else update_1 (p, value, RT <1 | 1 ); pushup (RT);} int query (int l, int R, int RT) {If (so N [RT]. L = L & Son [RT]. R = r) {return son [RT]. value;} int M = (son [RT]. L + son [RT]. r)/2; int ret = 0; If (r <= m) ret = query (L, R, RT <1); else if (L> m) ret = query (L, R, RT <1 | 1); else {ret = query (L, M, RT <1 ); RET + = query (m + 1, R, RT <1 | 1);} return ret;} int main () {int N; while (scanf ("% d", & N )! = EOF) {build (1, n, 1); int X [5010], sum = 0, ans; For (INT I = 1; I <= N; I ++) {scanf ("% d", & X [I]); X [I] + = 1; sum + = query (X [I], n, 1); update_1 (X [I],);} ans = sum; // cout <ans <Endl; For (INT I = 1; I <= N; I ++) {sum = sum + n + 1-2 * X [I]; ans = min (ANS, sum);} printf ("% d \ n ", ans);} return 0 ;}