1. Number of reverse orders
The so-called reverse order number refers to a sequence S [I], which counts the number of each number in a sequence that is larger than this number and comes before it, and then for all numbers, sum up the number.
For example, 4 3 1 2
4 first, so the number is 0
4 In front of 3, and 1 in number greater than 3
The first part of 1 is 4 3, and the number greater than 1 is 2.
2 is preceded by 4 3 1, and the number greater than 2 is 2
So the number of reverse orders is 1 + 2 + 2 = 5
Two methods to calculate the number of reverse orders
The general method is based on the reverse order number rule, and the result complexity is O (n * n). Generally, there are two methods to quickly calculate the reverse order number.
They are Merge Sorting and tree array.
2. Merge and sort
Merging and sorting comes from the idea of separation and governance. For details about the process, you can refer to other materials. The general idea is to divide the data in half. After sorting the data, you can combine the two ordered sequences.
How can I change the merge sort to calculate the number of reverse orders?
First, we assume that two ordered sequences a [I] and B [I] are merged:
Since a [I] is already ordered, for each element of a [I], it is placed before it and the number of elements larger than it is 0.
When B [I] contains elements smaller than a [I], we must insert B [I] elements to the front. That is to say, in the original position of B [I] to the position of the plug-in, all numbers are larger than those of B [I] and are placed before it.
So this is the number of B [I] As the New Insertion Location newPos-original location oldPos
So how can we do half of the sequence? We know that the Merge Sorting will continue to go down recursion, and after returning the recursion, it will be two sets of ordered sequences, and get the number of partial reverse orders,
So add this count operation to the Merge function.
Sample Code: int L [M];
Int R [M];
Const int Max = 1 <30;
_ Int64 change = 0;
Void Merge (int * data, int left, int divide, int right)
{
Int lengthL = divide-left;
Int lengthR = right-divide;
For (int I = 0; I <lengthL; ++ I)
{
L [I] = data [left + I];
}
For (int I = 0; I <lengthR; ++ I)
{
R [I] = data [divide + I];
}
L [lengthL] = R [lengthR] = Max;
Int I = 0;
Int j = 0;
For (int k = left; k <right; ++ k)
{
If (L [I] <= R [j])
{
Data [k] = L [I];
++ I;
}
Else
{
Change + = divide-I-left;
Data [k] = R [j];
++ J;
}
}
}
Void MergeSort (int * data, int left, int right)
{
If (left <right-1)
{
Int divide = (left + right)/2;
MergeSort (data, left, divide );
MergeSort (data, divide, right );
Merge (data, left, divide, right );
}
}
3. Tree Array
Another way to calculate the number of reverse orders is to use a tree array.
For small data, you can directly insert a tree array. For big data, You Need To discretization.
100 200 300 400 500 ---> 1 2 3 4 5
The tree array is used to solve the counting problem.
First, insert each number of sequence a [I] into the tree array in order. The inserted content is 1, indicating that a number is stored in the tree array.
Then, use the sum operation to obtain a number smaller than a [I]. The current I-sum indicates a number larger than a [I, this is repeated until all data is counted,
For example
4 3 1 2
I = 1: insert 4: update (), sum (4) returns 1, then the current greater than 4 is I-1 = 0;
I = 2: insert 3: update (3, 1), sum (3) returns 1, then I-1 = 1 if the current ratio is 3;
I = 3: insert 1: update (), sum (1) returns 1, then the current ratio of 1 is I-1 = 2;
I = 4: insert 2: update (2, 1), sum (2) returns 2, then I-2 = 2 is the current greater than 2;
The process is clear, so the number of reverse orders is 1 + 2 + 2 = 5
The sample code is as follows:
// Tree Array
_ Int64 sums [1005];
Int len;
Inline int lowbit (int t)
{
Return t & (t ^ (t-1 ));
}
Void update (int _ x, int _ value)
{
While (_ x <= len)
{
Sums [_ x] + = _ value;
_ X + = lowbit (_ x );
}
}
_ Int64 sum (int _ end) // get sum [begin end]
{
_ Int64 ret = 0;
While (_ end> 0)
{
Ret + = sums [_ end];
_ End-= lowbit (_ end );
}
Return ret;
}
// Calculate the number of reverse orders
_ Int64 ret = 0;
For (_ int64 I = 0; I <k; ++ I)
{
Update (a [I], 1 );
Ret + = (I + 1)-sum (a [I]);
}
The following are the questions about the number of reverse orders:
Http://poj.org/problem? Id = 2299
Http://poj.org/problem? Id = 3067