1010 Lehmer Code (35 points) (thinking + detailed explanation + learning of tree array + reverse order pair + map+vector) super detailed Come baby!!!

1: Title

According to Wikipedia: "In mathematics and in particular in combinatorics, the Lehmer code is a particular way to encode each possible permutation of a sequence of n numbers." To be more specific, for a given permutation of items {A

}, Lehmer code is a sequence of numbers {L hat L is the total number of items from Ato A which are less than A
. For example, given { 24, 35, 12, 1, 56, 23 }, the second Lehmer code L 2 is 3 since from 35 to 23 there are three items, { 12, 1, 23 }, less than the second item, 35.

Input Specification:
Each input file contains one test case. For each case, the first line gives a positive integer N (≤10
5
). Then N distinct numbers are given in the next line.

Output Specification:
For each test case, output in a line the corresponding Lehmer code. The numbers must be separated by exactly one space, and there must be no extra space at the beginning or the end of the line.

Sample Input:

6
24 35 12 1 56 23

No blank lines at the end
Sample Output:

3 3 1 0 1 0

2: Idea:

This question uses the related knowledge of tree array. In the application of tree array, there is an item to find the reverse order pair, but this question cannot be used directly. This question does not give the range of input numbers, so it cannot be solved directly by finding the reverse order pair,
Because a segment error will occur (because the number entered may be greater than 500000)
But we can convert the input numbers, sort them first, and take their subscript as their index
Instead, we can control the range of input numbers. This question has also clearly pointed out the input numbers
No repetition, so we can boldly use map to record their sorting

Here is an example to illustrate that we use ordered subscripts to replace numbers, so as to control the range of numbers, and the results are the same:

We can see that there are still three smaller numbers after the first number 4 and 4;

3: Upper Code:

 
/**
	Idea: this question does not give the range of input numbers, so it can not be solved directly by solving the reverse order pair
		  Because a segment error will occur (because the number entered may be greater than 500000) 
		  But we can convert the input numbers, sort them first, and take their subscript as their index
		  Instead, we can control the range of input numbers. This question has also clearly pointed out the input numbers
		  No repetition, so we can boldly use map to record their sorting 

*/ 
 
 
#include<bits/stdc++.h>
using namespace std;

int c[100005];

int lowbit(int x){
	return x&(-x);
}

//Single point update
void update(int x,int y,int n){
	
	while(x <= n){
		c[x] =  c[x] + y;
		x = x + lowbit(x);		
	}
	
} 

//Find prefix sum
int getSum(int pos){
	int sum = 0;
	
	while(pos > 0){
		sum += c[pos];
		pos = pos - lowbit(pos);  
	}
	
	return sum;
} 

 
int main(){
	
	int a[100005];
	vector<int> v1,v2,v3;
	map<int,int>m; 
	
	int N;
	
	memset(a,0,sizeof(a));
	memset(c,0,sizeof(c));
	
	cin >> N;
	
	for(int i = 0; i < N; i++){
		
		int temp;
		cin >> temp;
		
		a[i] = temp;
		v1.push_back(temp);
	}
	
	sort(v1.begin(),v1.end()); 
	
	for(int i = 0; i < N; i++){
		m[v1[i]] = i + 1;
	}
	
	
	for(int i = N - 1; i >= 0; i--){
		
		int num = m[a[i]];		
		update(num,1,100005);
		
		//Here, getSum(temp) represents the number smaller than temp, including the number of temp itself 
		int temp = getSum(num) - 1;
		
		v2.push_back(temp);

	}
	
	 for(int i = N-1; i >= 0; i--){
	 	
	 	if(i == N - 1){
	 		cout << v2[i];
		 }else{
		 	cout << ' ' << v2[i]; 
		 }
	 	
	 }
}

4: Introduce relevant knowledge

1: Tree array

(1) : illustration:

(2) : related introduction

Introduction to relevant knowledge:
1. Understand that figure A[i]: represents a normal array
C[i]: represents the sum of intervals

eg: c[1] =A[1]
c[2] = A[1] + A[2]
c[6] = A[5] + A[6]

2. Then how to represent the number represented by I in C[i]? At this time, lowbit(i) is used,
lowbit(i) = i & (-i)

eg: lowbit(6) = 2
lowbit(4) = 4

3.i + lowbit[i]: indicates the subscript of its parent node
eg:6 + lowbit(6) = 8

i - lowbit(i): the subscript indicating the jurisdiction on the left
eg:6 - lowbit(6) = 4

4. Related functions
(1) : get lowbit(i)

int lowbit (int i){
return i & (-i);
}   

(2) : update the value of a single point, that is, if you add a certain number to a value in the interval, its parent node will be updated
The corresponding value is also increased
Eg: if a [1] is larger than before, then C[1] is also larger than before. Its parent node C[2],
Also, the parent node of c[2] will become larger

void update(int x,int y,int n) {/ / parameter: indicates that y is added at position x, and the array length is n

while(x <= n){
c[x] = c[x] + y;
x = x + lowbit(x);//Get parent node 
}	

}

(3) : prefix sum
eg: find the sum of the first 6 numbers
sum[6] = A[1] + A[2] + A[3]+ A[4]+ A[5] + A[6]

Because: C[6] = A[5] + A[6]
C[4] = A[1]+A[2]+A[3]+A[4]
So sum[6] = C[6] + C[4]

int getSum(int pos){
int sum = 0;

while(pos > 0){
sum += C[pos]

pos = pos - lowbit[pos]
}

return sum;
}

2: Example to find interval sum

	Title: find the sum of each number in a certain interval
	Input format
	The first line contains two positive integers n,m,Respectively represent the number and number of numbers in the sequence
	Total number of operations
	The second line contains n An integer separated by spaces,Among them i A number represents a number
	Column i Initial value of item
	next m Each row contains 3 integers,Represents an operation,The details are as follows
	·1 x k meaning:Will be the first x Number plus k
	·2 x y meaning:Output interval{x,y}Sum of each number in
	Output format
	The output contains several lines of integers,This is the result of all operations 2.
	
	
	Input example: 5
			   1 5 4 2 3
			   1 1 3
			   2 2 5
			   1 3 -1
			   1 4 2
			   2 1 4
			   
		Output: 14
			  16
/**
	Title: find the sum of each number in a certain interval
	Input format
	The first row contains two positive integers n and m, which respectively represent the sum of the numbers in the sequence
	Total number of operations
	The second line contains n integers separated by spaces, where the ith number represents a number
	Initial value of column item i
	The next m lines contain three integers, representing an operation, as follows
	·1 x k Meaning: add k to the x-th number
	·2 x y Meaning: the sum of each number in the output interval {x,y}
	Output format
	The output contains several lines of integers, which is the result of all operation 2.
	
	
	Input example: 5
			   1 5 4 2 3
			   1 1 3
			   2 2 5
			   1 3 -1
			   1 4 2
			   2 1 4
			   
		Output: 14
			  16
			  
	
	Introduction to relevant knowledge:
		1.Understand figure A[i]: it represents a normal array
		         C[i]:Represents the sum of intervals 
		  
		    eg:  c[1] =A[1]
		  	     c[2] = A[1] + A[2]
		  	     c[6] = A[5] + A[6]
		   
		2.So how to represent the number represented by I in C[i]? At this time, lowbit(i) is used,
			lowbit(i) = i & (-i)
		
		    eg: lowbit(6) = 2
		     	lowbit(4) = 4
			
		3.i + lowbit[i]: Subscript representing its parent node
		  eg:6 + lowbit(6) = 8
		  
		  i - lowbit(i): Subscript indicating the jurisdiction to the left
		  eg:6 - lowbit(6) = 4
		  
		4.Related functions
			(1):Get lowbit(i)
				
				int lowbit (int i){
					return i & (-i);
				}   
		  	
		  	(2):Updating the value of a single point means that if you add a certain number to a value in the interval, its parent node will be updated
			  	The corresponding value is also increased
				  eg: A[1]If it is larger than before, then C[1] is also larger than before. Its parent node C[2],
				  Also, the parent node of c[2] will become larger
				  
				 void update(int x,int y,int n){//Parameter: indicates that y is added at the x position, and the array length is n
				  
					while(x <= n){
						c[x] = c[x] + y;
						x = x + lowbit(x);//Get parent node 
					}	
							
				}
				   
			(3):Prefix Sum 
				eg:Find the sum of the first 6 numbers
					sum[6] = A[1] + A[2] + A[3]+ A[4]+ A[5]	+ A[6]
					
				Because: C[6] = A[5] + A[6]
					  C[4] = A[1]+A[2]+A[3]+A[4]	
				So sum[6] = C[6] + C[4]	
				
				int getSum(int pos){
					int sum = 0;
					
					while(pos > 0){
						sum += C[pos]
						
						pos = pos - lowbit[pos]
				    }
				    
				    return sum;
				}
				 	    
	
	
	

*/





#include<bits/stdc++.h>
using namespace std;

int c[1000] = {0};

int lowbit(int x){
	return x&(-x);
}

//Update single node 
void update(int x,int y,int n){
	while(x <= n){
		c[x] = c[x] + y;
		x = x + lowbit(x);
	}
}

//Prefix Sum 
int getSum(int pos){
	int sum = 0;
	
	while(pos > 0){
		sum += c[pos];
		pos = pos - lowbit(pos);	
	}
	
	return sum;
} 
 



int main(){
	
	int N,M;
	int a[1000];
	memset(a,0,sizeof(a));
	
	cin >> N >> M;
	
	for(int i = 1; i <= N; i++){
		
		cin >>a[i];
		//Here is the operation of assigning values to C[i]. Since the initial values in a[i] are all 0, you can start updating 
		update(i,a[i],N); 
	}
	
	for(int i = 0; i < M; i++){
		
		int operation,num1,num2;
		
		cin >> operation >> num1 >> num2;
		 
		if(operation == 1){
			update(num1,num2,N);
		}else if(operation == 2){
			 cout << getSum(num2) - getSum(num1-1) << endl;
		}else{
			cout << "Your input is incorrect!!"; 
		} 
			
	}
	
//test data	
//	for(int i = 1; i <= N; i++){
//		cout << c[i] << ' ';
//	} 
	
//	cout << a[99];
		
} 


/**

	·1 x k Meaning: add k to the x-th number
	·2 x y Meaning: the sum of each number in the output interval {x,y}
	Output format
	The output contains several lines of integers, which is the result of all operation 2.
	
	
	Input example: 5
			   1 5 4 2 3
			   1 1 3           
			   2 2 5
			   1 3 -1
			   1 4 2
			   2 1 4
			   
		Output: 14
			  16
*/


//5 5
//1 5 4 2 3
//1 1 3
//2 2 5
//1 3 -1
//1 4 2
//2 1 4

3: Reverse order pair

What is reverse order pair
What is reverse order pair
Let A be an ordered set of n numbers (> 1), where all numbers are different. If there are positive integers i,j
If 1 < = I < J < = n and A [i] > A [J], then < A [i], A [J] > this ordered symmetry is an inverse pair of A, also known as the inverse number. For example
There are (3,1) (32) (42) (5,2) reverse pairs of array (3,1,4,5,2), a total of 4

Idea: the number of N input 3 1 4 5 2
Each input value is at the position corresponding to A[i](i = input value), A[3] = 1,A[1] = 1;
Where a [], C [], initialization is 0, and each time a[i] changes, the corresponding value of C[i] is updated
Then, the number of numbers larger than it in front = i - (the number of numbers smaller than it in front)
= i - getSum(a[i])

/**
	What is reverse order pair
	What is reverse order pair
	Let A be an ordered set of n numbers (> 1), where all numbers are different. If there are positive integers i,j
	If 1 < = I < J < = n and A [i] > A [J], then < A [i], A [J] > this ordered symmetry is an inverse pair of A, also known as the inverse number. For example
	There are (3,1) (32) (42) (5,2) reverse pairs of array (3,1,4,5,2), a total of 4 

	Idea: the number of N input 3 1 4 5 2
	     Each input value is at the position corresponding to A[i](i = input value), A[3] = 1,A[1] = 1;
		 Where a [], C [], initialization is 0, and each time a[i] changes, the corresponding value of C[i] is updated
		 
		 Then, the number of numbers larger than it in front = i - (the number of numbers smaller than it in front)
								  =	i - getSum(a[i]) 
	
*/ 


#include<bits/stdc++.h>
using namespace std;

int c[1000];

int lowbit(int x){
	return x&(-x);
}

//Single point update
void update(int x,int y,int n){
	
	while(x <= n){
		c[x] =  c[x] + y;
		x = x + lowbit(x);		
	}
	
} 

//Find prefix sum
int getSum(int pos){
	int sum = 0;
	
	while(pos > 0){
		sum += c[pos];
		pos = pos - lowbit(pos);  
	}
	
	return sum;
} 

 
int main(){
	
	int a[1000],b[1000];
	int N;
	
	memset(a,0,sizeof(a));
	memset(b,0,sizeof(b));
	memset(c,0,sizeof(c));
	
	cin >> N;
	
	for(int i = 1; i <= N; i++){
		
		int temp;
		cin >> temp;
		
		a[temp] = 1;
		update(temp,a[temp],1000);
		
		//Here, getSum(temp) represents the number smaller than temp 
		
		cout << i - getSum(temp) << ' ';	
		
	}
	
}

4: Brothers who are not skilled in map and vector containers can take a look at this connection

Basic usage of map
Basic usage of vector

5: Learning records

I worked on this problem for three nights. I just got it and did it directly. Later, I began to learn tree array, find interval sum and reverse order pairs, and slowly formed the solution of this problem

Code for the first time: the past two points

#include<bits/stdc++.h>
using namespace std;

int main(){
	
	int N;
	vector<int> v1,v2;
	
	cin >> N;
	
	for(int i = 0; i < N; i++){
		int temp;
		cin >> temp;	
		v1.push_back(temp);
	}
	
	for(int i = 0; i < N; i++){
		
		int count = 0;
		
		for(int j = i+1; j < N; j++){
			
			if(v1[i] > v1[j]){
				count++;
			}
		}
		
		v2.push_back(count);
		
	}
	
	int flag = 0;
	
	for(int i = 0; i < N; i++){
		
		if(flag == 0){
			cout << v2[i];
		}else{
			cout << ' ' << v2[i];
		}
		
		flag = 1;
	}
		
} 

/**
6
24 35 12 1 56 23

3 3 1 0 1 0


*/

The second time I did the code, the last 4 points, but there was still a point timeout

#include<bits/stdc++.h>
using namespace std;

int c[1000005];

int lowbit(int x){
	return x&(-x);
}

//Single point update
void update(int x,int y,int n){
	
	while(x <= n){
		c[x] =  c[x] + y;
		x = x + lowbit(x);		
	}
	
} 

//Find prefix sum
int getSum(int pos){
	int sum = 0;
	
	while(pos > 0){
		sum += c[pos];
		pos = pos - lowbit(pos);  
	}
	
	return sum;
} 

 
int main(){
	
	int a[1000005],b[10000];
	vector<int> v1,v2;
	int N;
	
	int aa = 1;
	v1.push_back(aa);
	v2.push_back(aa);
	
	memset(a,0,sizeof(a));
	memset(c,0,sizeof(c));
	
	cin >> N;
	
	for(int i = 1; i <= N; i++){
		
		int temp;
		cin >> temp;
	
		v1.push_back(temp);
	}
	
	for(int i = N; i >= 1; i--){
		
		int num = v1[i];
		
		a[num] = 1;
		update(num,a[num],1000005);
		
		//Here, getSum(temp) represents the number smaller than temp, including the number of temp itself 
		int temp = getSum(num) - 1;
		
		v2.push_back(temp);

	}
	
	 for(int i = N; i >= 1; i--){
	 	
	 	if(i == N){
	 		cout << v2[i];
		 }else{
		 	cout << ' ' << v2[i]; 
		 }
	 	
	 }
		

}

Come on, learning is like divide and conquer algorithm, which decomposes a large problem into small problems, and then solves them one by one. The final results are combined into the solutions of large problems,

Tags: C++ Algorithm data structure

Posted on Thu, 07 Oct 2021 13:17:55 -0400 by patricklcam