题目描述
Let { A1,A2,…,An } be a permutation of the set{ 1,2,…, n}. If i < j and Ai > Aj then the pair (Ai,Aj) is called an “inversion” of the permutation. For example, the permutation {3, 1, 4, 2} has three inversions: (3,1), (3,2) and (4,2).
The inversion table B1,B2,…,Bn of the permutation { A1,A2,…,An } is obtained by letting Bj be the number of elements to the left of j that are greater than j. (In other words, Bj is the number of inversions whose second component is j.) For example, the permutation:
{ 5,9,1,8,2,6,4,7,3 }
has the inversion table
2 3 6 4 0 2 2 1 0
since there are 2 numbers, 5 and 9, to the left of 1; 3 numbers, 5, 9 and 8, to the left of 2; etc.
Perhaps the most important fact about inversions is Marshall Hall’s observation that an inversion table uniquely determines the corresponding permutation. So your task is to convert a permutation to its inversion table, or vise versa, to convert from an inversion table to the corresponding permutation.
Input:
The input consists of several test cases. Each test case contains two lines.
The first line contains a single integer N ( 1 <= N <= 50) which indicates the number of elements in the permutation/invertion table.
The second line begins with a single charactor either ‘P’, meaning that the next N integers form a permutation, or ‘I’, meaning that the next N integers form an inversion table.
Following are N integers, separated by spaces. The input is terminated by a line contains N=0.
Output:
For each case of the input output a line of intergers, seperated by a single space (no space at the end of the line). If the input is a permutation, your output will be the corresponding inversion table; if the input is an inversion table, your output will be the corresponding permutation.
Sample Input:
9
P 5 9 1 8 2 6 4 7 3
9
I 2 3 6 4 0 2 2 1 0
0
Sample Output:
2 3 6 4 0 2 2 1 0
5 9 1 8 2 6 4 7 3
核心思路
-
permutation -> inversion:
因为n的数据范围不大,所以可以用朴素版的双指针算法。
双指针 : i 指向目标数字 ,j 从头向后扫描寻找比i要大的数,遇到i 就回滚,寻找一个数 i+1; -
inversion -> permutation:
类似哈希表的方法。
附带本人提交情况
提交运行时间,4毫秒。
C++代码
#include<iostream>
#include<cstring>
using namespace std;
const int N = 60;
int a[N],t[N];
int n;
char c;
void permutation_to_inversion()
{
for(int i=1;i<=n;i++) // 双指针 :i 指向目标数字 ,j 从头向后扫描寻找比i要大的数,遇到i 就回滚,寻找一个数 i+1;
{ int j=1;
while(j<=n)
{
if(a[j]==i)break;
if(a[j]>i)
{
t[i]++; j++;
}
else j++;
}
}
}
void inversion_to_permutation()
{
int i,j,count,k;
for(j=1; j<=n; j++)
{
count = 0;
for(i=1; i<=n && count<a[j]; i++)
{ // 扫描寻找 符合的位置
if( t[i]==0 )
count++;
}
if( t[i] != 0) // 位置发生了冲突。
for(k=i+1; k<=n; k++)
if( t[k] == 0 )
{
i = k;
break;
}
t[i] = j;
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
while(cin>>n&&n!=0)
{
cin>>c;
memset(a,0,sizeof(a));
memset(t,0,sizeof(t));
for(int i=1;i<=n;i++) cin>>a[i];
if(c=='P') permutation_to_inversion();
else inversion_to_permutation();
for(int i=1;i<=n;i++)
{ if(i!=1)cout<<" ";
cout<<t[i];
}
cout<<"\n";
}
return 0;
}