I have reviewed this question.Merge SortingAt the same time, we understand that merging and sorting in the arrayNumber of reverse ordersIt's also the first time I 've learned this application.Tree Array
Question:
A very direct description of the question. Enter an array for the question. The size of the array elements is in the range of 0-> 999.999.999. The number of elements ranges from 0.
The question requires the exchange of adjacent elements to make the input array orderly, and the number of exchanges required?
For example, if you enter 9 1 0 5 4 and change it to 0 1 4 5 9, how many exchanges are required.
Thought 1:
The question asks for the total number of exchanges. This question is the same as "what is the total number of reverse orders for an array ?"
For example, if the number of reverse orders in the input array 9 1 0 5 4 is 6, what is the total number of exchanges?
1st bubble results, 0 9 1 5 4 exchanged 2 times, it is equal to the number of 0 reverse orders.
2nd bubble results, 0 1 9 5 4 exchange once, it is equal to the number of 1 reverse orders.
3rd bubble results, 0 1 4 9 5 exchanged 2 times, is equal to the number of 4 reverse orders.
4th bubble results, 0 1 4 5 9 exchanged once, is equal to the number of 5 reverse orders.
5th bubble results, 0 1 4 5 9 exchanged 0 times, it is equal to the number of 9 reverse orders.
2 + 1 + 2 + 1 + 0 = 6
So the problem is to find the reverse order of the array?
Therefore, we only need to traverse each bit, calculate the number of reverse orders for each bit, and sum the values. The implementation is omitted, and the time complexity is O (n ^ 2 ).
The following train of thought 2 and train of thought 3 will discuss the implementation of two algorithms with time complexity of O (nlogn.
Idea 2:
Merge Sorting is used to calculate the reverse Number of arrays. This is an application of Merge Sorting, but it has never been known before and is too weak.
The idea is described in the previous log (sort-merge sort and reverse order algorithm), which is to add a statement on the basis of merge sort.
I will not discuss the specific ideas. Paste the implementation code below:
/* <Br/> calculate the number of reverse orders of an array. the time complexity of Merge Sorting is O (nlogn), which increases the speed of simple Bubble sorting. <Br/> only the result + = middle-I + 1 is added on the basis of Merge Sorting. <br/> If the number in the next array is smaller than that in the previous array, when both input [J] <input [I], <br/> our counter result needs to be added, the increase should be the number of remaining data in the previous Array Middle-I + 1, <br/> the purpose of merging and sorting is to merge two sorted arrays into an ordered array. <Br/> This is the first number of input [J] of the next array. If you want to order it, it must be switched to the previous middle-I + 1 digit. <Br/> note that the result type is of the Longlong type. <Br/> */<br/> # include <iostream> <br/> # include <stdio. h> <br/> # include <stdlib. h> <br/> # define maxn 500005 <br/> using namespace STD; <br/> int N; <br/> int input [maxn] = {0 }; <br/> int TMP [maxn]; <br/> long result; <br/> void merge (INT left, int middle, int right) <br/>{< br/> int I, j, k; <br/> I = left, j = middle + 1, k = 1; <br/> while (I <= Middle & J <= right) <br/> {<br/> If (input [J] <input [I ]) <Br/> {<br/> TMP [k ++] = input [J ++]; <br/> result + = middle-I + 1; // Add a statement. <Br/>}< br/> else <br/> TMP [k ++] = input [I ++]; <br/>}</P> <p> while (I <= middle) TMP [k ++] = input [I ++]; <br/> while (j <= right) TMP [k ++] = input [J ++]; </P> <p> for (I = left, k = 1; I <= right; I ++, K ++) <br/> input [I] = TMP [k]; <br/>}< br/> void merge_sort (INT left, int right) <br/>{< br/> If (left <right) <br/>{< br/> int middle = (left + right)/2; <br/> merge_sort (left, middle ); <br/> merge_sort (middle + 1, right); <br/> Merge (left, middle, right ); <br/>}< br/> int main () <br/>{< br/> int I, J, K; <br/> while (true) <br/> {<br/> CIN> N; <br/> If (n = 0) break; </P> <p> for (I = 1; I <= N; I ++) <br/> scanf ("% d", & input [I]); </P> <p> result = 0; <br/> merge_sort (1, N); </P> <p> cout <result <Endl; <br/>}< br/> return 0; <br/>}< br/>
Thought 3:
Tree array,Specifically, it is a discretization + tree array. This is also the first question of learning tree arrays.
The general process of the algorithm is:
1. First, discretization the input array so that each element is close, rather than discrete,
2. Then, use the standard operation of the tree array to accumulate the number of reverse orders of the array.
Detailed explanation of the algorithm:
1. Why is there a discrete process?
At first, we thought that 999.999.999 is enough for the int storage type.
There are only 500000 numbers. Why discretization?
At first, I couldn't figure it out. Later I understood that when I was using a tree array,
The tree array C [I] is built on an array that is somewhat bit-store,
It is not simply built on the input array.
For example, if you enter a 9 1 0 5 4, then the C [I] tree array is created in,
Subscript 0 1 2 3 4 5 6 7 8 9
Array 1 1 0 0 1 1 0 0 0 1
Now, because the number 999999999 is large compared with the number 500000,
Therefore, if an array is used for storage, 999999999 of the space is required to store the input data.
This is a waste of space and the question is not allowed. Therefore, we want to use discretization,
The discretization results can be more intensive.
2. How to perform discrete operations on the input array?
Discretization is a common technique. Sometimes the data range is too large and can be scaled down to the scope that we can process;
Because the range of the number to be sorted is 0---999 999 999; obviously, the array cannot be so large;
The maximum range of N is 500 000, so the given number must be 1 .... N creates a one-to-one ing;
① Of course, map can be used for building, and the efficiency may be low;
② Here we use a struct
Struct Node
{
Int V, ord;
} P [1, 510000]; and an array a [2, 510000];
Where V is the original input value, Ord is the subscript, and then the struct is sorted by V from small to large;
At this time, the subscript of the V and struct is a one-to-one correspondence, and the original size relationship is satisfied;
For (I = 1; I <= N; I ++) A [p [I]. ord] = I;
Then array a stores all the original size information;
For example, 9 1 0 5 4 ------- the discrete AA array is 5 2 1 4 3;
The specific process can be written and written by yourself.
3. After discretization, how can I use the discrete result array for tree Array Operations to calculate the number of reverse orders?
If the data is not very big, you can insert them into the tree array one by one,
Insert a number to calculate the number smaller than him,
The corresponding reverse order is I-getsum (AA [I]),
Where I represents the number of inserts currently,
Getsum (AA [I]) is a number smaller than AA [I,
I-sum (AA [I]) is a number larger than AA [I], that is, the number of reverse orders
However, if the data is large, the discretization method must be used.
Assume that the input array is 9 1 0 5 4, and the discrete result AA [] = {5, 2, 3 };
Based on the intermediate results of discrete results, the process of calculating the number of reverse orders is such a process.
1. Input 5. Call Update (5, 1) and set the 5th bits to 1.
1 2 3 4 5
0 0 0 0 1
Is there a number between 1 and 5 smaller than 5? The getsum (5) = 1 operation of the tree array is used here,
Now we can use the input subscript 1-getsum (5) = 0 to obtain the number of reverse orders for 5 is 0.
2. Input 2, call update (2, 1), and set the 2nd bits to 1.
1 2 3 4 5
0 1 0 0 1
Is there a number that is 1-2 lower than 2? The getsum (2) = 1 operation of the tree array is used here,
Now we can use the input subscript 2-getsum (2) = 1 to obtain the number of reverse orders for 2 is 1.
3. Input 1, call update (1, 1), and set the 1st bits to 1.
1 2 3 4 5
1 1 0 0 1
Is there a number that is 1-1 lower than 1? The getsum (1) = 1 operation of the tree array is used here,
Now we can use the input subscript 3-getsum (1) = 2 to obtain the number of reverse orders for 1 is 2.
4. Input 4, call Update (4, 1), and set the 5th bits to 1.
1 2 3 4 5
1 1 0 1 1
Is there a number between 1 and 4 smaller than 4? The getsum (4) = 3 operation of the tree array is used here,
Now we can use the input subscript 4-getsum (4) = 1 to obtain the number of reverse orders for 4 as 1.
5. Input 3, call Update (3, 1), and set the 3rd bits to 1.
1 2 3 4 5
1 1 1 1
Is there a number between 1 and 3 smaller than 3? The getsum (3) = 3 operation of the tree array is used here,
Now we can use the input subscript 5-getsum (3) = 2 to obtain the number of reverse orders for 3 is 2.
6. 0 + 1 + 2 + 1 + 2 = 6. This is the final number of reverse orders.
To analyze the time complexity, we first use quick sorting. the time complexity is O (nlogn ),
Each number is inserted cyclically. Each time a number is inserted, updata () and getsum () are called respectively ()
External Loop N, updata () and getsum () time O (logn) => time complexity or O (nlogn ).
The final sum is O (nlogn ).
The code is implemented as follows:
# Include <iostream> <br/> # include <stdio. h> <br/> # include <stdlib. h> <br/> # define maxn 500005 <br/> using namespace STD; <br/> int N; <br/> struct node <br/>{< br/> int value; <br/> int num; <br/>} input [maxn]; // store the input array <br/> int AA [maxn]; // store the result of the discretization operation <br/> int CMP (const void *, const void * B) // for sorting during discretization, use <br/>{< br/> return (* (node *) ). value-(* (node *) B ). value; <br/>}< br/> /////////////////////////////// //// // The standard tree Array operation <br/> /////////////////////////////////// /// // <br/> int C [maxn]; // This is a tree array, which is cleared at the beginning. <br/> int lowbit (int x) <br/>{< br/> return X & (-x ); <br/>}< br/> void Update (int n, int delta) <br/>{< br/> while (n <= N) <br/>{< br/> C [N] + = delta; <br/> N + = lowbit (N ); <br/>}< br/> int getsum (int n) <br/>{< br/> int result = 0; <br/> while (n> = 1) <br/> {<br/> result + = C [N]; <br/> N-= lowbit (N ); <br/>}< br/> return result; <br/>}< br/> int main () <br/>{< br/> int I, j, k; <br/> while (true) <br/>{< br/> CIN> N; <br/> If (n = 0) break; <br/> // input processing and discretization <br/> for (I = 1; I <= N; I ++) <br/>{< br/> scanf ("% d", & input [I]. value); <br/> input [I]. num = I; <br/>}< br/> qsort (& input [1], n, sizeof (node), CMP ); <br/> for (I = 1; I <= N; I ++) AA [input [I]. num] = I; </P> <p> // use the tree array data structure operation to calculate the number of reverse orders <br/> for (I = 1; I <= N; I ++) <br/> C [I] = 0; <br/> long result = 0; <br/> for (I = 1; I <= N; I ++) <br/>{< br/> Update (AA [I], 1 ); <br/> result + = (I-getsum (AA [I]); <br/>}</P> <p> cout <result <Endl; <br/>}< br/> return 0; <br/>}