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,