问题描述
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. your task is to convert a permutation to its inversion table, or vise versa, to convert from an inversion table to the corresponding permutation. (Use divide and conquer method)
翻译
设 { A1,A2,...,An } 是集合 { 1,2,..., n} 的排列。如果 i < j 且 Ai > Aj,那么 (Ai,Aj) 对称为该排列的 "反转"。例如,排列 {3, 1, 4, 2} 有三个反转:(3,1)、(3,2) 和 (4,2)。将 Bj 设为 j 左边大于 j 的元素的个数,就可以得到排列 { A1,A2,...,An } 的反转表 B1,B2,...,Bn (换句话说,Bj 就是第二个分量是 j 的反转数):
{ 5,9,1,8,2,6,4,7,3 }
的反转表为
2 3 6 4 0 2 2 1 0.
因为在 1 的左边有 2 个数,即 5 和 9;在 2 的左边有 3 个数,即 5、9 和 8;等等。你的任务是将一个排列转换成它的反转表,或者反过来,将一个反转表转换成相应的排列。(使用分而治之法)
思路
待定
代码
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string>
#include <algorithm>
#include <stdlib.h>
using namespace std;
const int N = 1e6 + 10;
int resetTable[N] = { 0 }; int tem2[N] = { 0 };//复位答案
int inversionTable[N] = { 0 }; int ans = 0; int tem1[N];//反转表
void inverse(int a[], int l, int r)
{
int mid = l + r >> 1;
if (l <r)
{
inverse(a, l, mid );
inverse(a, mid + 1, r);
}
int i = l, j = mid + 1, k = 0;
while (i <= mid && j <= r)
{
if (a[i] <=a[j]) {
tem1[k++] = a[i++];
}
else
{
tem1[k++] = a[j++];
inversionTable[a[j - 1]] += mid-i+1;
}
}
while (i <= mid)
{ tem1[k++] = a[i++];
}
while (j <= r)
{
tem1[k++] = a[j++];
}
for (int i = l, j = 0; i <= r; j++, i++)
a[i] = tem1[j];
}
void reSet(int a[], int n)
{
int i,j,k, count;
for (i = 1; i <= n; i++)
{
count = 0;
for (j = 1; j <= n && count < a[i]; j++)
{
if (tem2[j] == 0)
{ count++;
}
}//找到n个空位后,停止找空位,放入i
if(tem2[j]!=0)//如果下一个位置不为空位,
for(k=j+1;k<=n;k++)//遍历进行找空位
if (tem2[k] == 0)
{
j = k;
break;
}
tem2[j] = i;//在下一个位置放入i
}
//int i, j, count, k;
//for (i = 1; i <= n; i++)
//{
// count = 0;
// for (j = 1; j <= n && count < a[i]; j++)
// { // 扫描寻找 符合的位置
// if (tem2[j] == 0)
// count++;
// }
// if (tem2[j] != 0) // 位置发生了冲突。
// for (k = j + 1; k <= n; k++)
// if (tem2[k] == 0)
// {
// j = k;
// break;
// }
// tem2[j] = i;
//}
}
int main()
{
int n;
cin >> n;
int a[N];
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
inverse(a, 1,n);
cout << "The inversion table is following :" << endl;
for (int i = 1; i <= n; i++)
cout << inversionTable[i] << " ";
reSet(inversionTable, n);
cout << endl;
cout << "The reSet table is following :" << endl;
for(int i=1;i<=n;i++)
cout << tem2[i] << " ";
return 0;
}