poj 2085 Inversion 已知数个数为n,逆序数为ver,求最小满足条件的排列

Inversion
Time Limit: 1000MS   Memory Limit: 30000K
Total Submissions: 2937   Accepted: 1308

Description

The inversion number of an integer sequence a1, a2, . . . , an is the number of pairs (ai, aj) that satisfy i < j and ai > aj . Given n and the inversion number m, your task is to find the smallest permutation of the set { 1, 2, . . . , n }, whose inversion number is exactly m. 
A permutation a1, a2, . . . , an is smaller than b1, b2, . . . , bn if and only if there exists an integer k such that aj = bj for 1 <= j < k but ak < bk.

Input

The input consists of several test cases. Each line of the input contains two integers n and m. Both of the integers at the last line of the input is −1, which should not be processed. You may assume that 1 <= n <= 50000 and 0 <= m <= n(n − 1)/2.

Output

For each test case, print a line containing the smallest permutation as described above, separates the numbers by single spaces.

Sample Input

5 9
7 3
-1 -1

Sample Output

4 5 3 2 1
1 2 3 4 7 6 5
 
 
 
 
 
 
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
vector<int> a;
int main()
{
    int n,ver;
    while(scanf("%d%d",&n,&ver)==2&&n>0)
    {
        a.clear();
        int l;//共需要几个数才能满足逆序数ver
        for(l=0;l*(l+1)/2<ver;l++);l++;
        //要尽量小,所以用后面l个数,前面的从小到大排列
        for(int i=1;i<=n-l;i++) a.push_back(i);
        int res=ver-(l-2)*(l-1)/2;
        //jump表示在[n-l+1,n]中排res+1的数
        int jump=n-l+1+res;
        a.push_back(jump);
        for(int i=n;i>=n-l+1;i--)
        {
            if(i!=jump) a.push_back(i);
        }
        for(int i=0;i<n;i++)
        {
            if(i==0) printf("%d",a[0]);
            else printf(" %d",a[i]);
        }printf("/n");
    }
    return 0;
}

你可能感兴趣的:(poj 2085 Inversion 已知数个数为n,逆序数为ver,求最小满足条件的排列)