Ultra-QuickSort OpenJ_Bailian-2299 reverse order pair + tree array + discretization (realized by reordering the structure)

The main idea of ​​the topic: When entering an array sequence and requesting the entire sequence to be bubble sorted, the total number of times each element needs to be exchanged.

enter:

The input contains several test cases. Each test case begins with a line containing a single integer n <500,000 (the length of the input sequence). Each of the next n rows contains an integer, that is, 0≤a [i]≤999,999,999, which is the i-th input sequence element. The input is terminated by a sequence of length n=0. This sequence must not be processed.

Output:

For each input sequence, the program will print a single line containing the integer op, where op is the minimum number of exchange operations required to bubble sort the given input sequence.

Ideas:


The amount of input data is within 5e5, so the amount of data is not a problem, but the problem is that the value is too large 9.9 billion, if the direct processing time complexity will be greatly increased (because the tree array uses lowbit to operate), so the data needs to be Discretize.

The so-called discretization (big guy skipping) can be understood in the ontology as not changing the relative magnitude of each value, and assigning a new set of values ​​to them.

For example: 30 20 10 40 50 60 This set of data after sorting is 10 20 30 40 50 60

If we change its value to 3 2 1 4 5 6 after sorting, it becomes 1 2 3 4 5 6

The above operation makes the various input positions re-sorted (sorting only depends on the relative size of each value), and we can know that their sorting exchange times are the same, so we can discretize the first set of data into the second set of data , This can greatly optimize the time complexity.


The input data is stored in a structure, mainly storing val (value) and id (subscript serial number). This is a discretization must be done, and this idea is also used in many places, so it needs to be written down. The main purpose of saving subscripts is to record their previous position when sorting values, and discretize them into new values ​​according to their previous positions. See the code for details.


Let's talk about the idea of ​​solving this problem, because it is how many exchanges should be exchanged in the bubble sorting (assuming it is in ascending order). Considering the problem from another perspective, we find that as long as we know how many reverse pairs are in the entire sequence, we know how many exchanges are needed , Because we have to exchange every pair of reversed pairs.

To find the reverse pair of this sequence, we use a tree array to store how many numbers are smaller than it before each value. Because it is in ascending order, we need to check from back to front how many numbers of each number are smaller than it. When checking, we follow the discretized value and maintain the tree array on the number axis, so that each value obtained by getNum is For the number of numbers smaller than x, each time you find a number from back to front, add 1 to the number and put it into the tree array (this is a very important idea), and then the next time you add it, you can Ensure the correctness of the answer.

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 5e5 + 5;
typedef long long ll;
ll a[maxn], C[maxn << 1];
//0≤a [i]≤999,999,999  数据太大要需要进行离散化 
int n;
struct N{
	ll v;
	int id;
	bool operator < (const N & w)const{
		return v < w.v;
	}
}no[maxn];

void update(int x, int v){
	for(int i = x;i <= n;i += i & (-i)){
		C[i] += v;
	}
}

int getNum(int x){
	int ans = 0;
	for(int i = x;i > 0;i -= i & (-i)){
		ans += C[i];
	}
	return ans; 
}

int main(){
	while(scanf("%d",&n), n){
		memset(C, 0, sizeof C);
		for(int i = 1;i <= n;i++){
			scanf("%lld", &no[i].v);
			no[i].id = i;
		}
		sort(no + 1, no + n + 1);
		//更新a数组 
		for(int i = 1;i <= n;i++) {
			a[no[i].id] = i;
		}
		ll ans = 0;
		for(int i = n; i >= 1;i--){
			ans += getNum(a[i] - 1);
			update(a[i], 1);
		}
		printf("%lld\n",ans);	
	}
	
	return 0;
}

 

Guess you like

Origin blog.csdn.net/qq_40596572/article/details/104007691