组合数学习题(由逆序列生成排列)

/****************************************************
采用线段树统计空格个数,从而确定某个数字应该存放在
排列中的位置,总时间复杂度为n*logn
*****************************************************/

#include<iostream>
#include<fstream>
using namespace std;

#define MAXN 1001
#define L(x) (x<<1)
#define R(x) ((x<<1)|1)
fstream fout ("out.txt",ios::out);

struct TreeNode
{
    int l, r, space, p;
};
TreeNode node[MAXN*5];

void build_tree ( int u, int l, int r )
{
    node[u].l = l;
    node[u].r = r;
    node[u].space = r-l+1;
    node[u].p = r;
    if ( l == r ) return;
    int mid = (l+r) >> 1;
    build_tree ( L(u), l, mid );
    build_tree ( R(u), mid+1, r );
}

int position ( int u, int num ) // 确定下标,使得它本身是第num个空位置
{
    node[u].space--;
    if ( node[u].l == node[u].r )
        return node[u].l;

    if ( num <= node[L(u)].space )
        return position ( L(u), num );
    else
        return position ( R(u), num - node[L(u)].space );
}

void ReordertoPermu ( int n, int *reorder, int *permu ) //将逆序列转换为排列
{
    for ( int i = 1; i <= n; i++ )
    {
        int pos = position ( 1, reorder[i]+1 );
        permu[pos] = i;
    }
}

int main()
{
    int n;
    int reorder[MAXN], permu[MAXN];

    while ( cin >> n ) // 输入逆序列的大小
    {
        build_tree ( 1, 1, n );
        for ( int i = 1; i <= n; i++ )
            cin >> reorder[i];

        ReordertoPermu ( n, reorder, permu );
        for ( int i = 1; i <= n; i++ )
            fout << permu[i];
        fout << endl;
    }
    return 0;
}

你可能感兴趣的:(组合数学习题(由逆序列生成排列))