Inversion
Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 4176 | Accepted: 1857 |
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.
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
Source
题目大意:
给出n和m,求1~n组成的序列中逆序对数为m的最小一个序列。
有多组数据,-1 -1表示输入结束。
思路:
首先,ans一定会是个先上升再下降的数列。(如右图)
而且,上升的序列是逐个加一,抛出尾数,即折点数。
而下降的序列就是剩下的数也抛去折点数,依次输出。
因此,只需要求出折点数x和下降序列的长度k即可。
右图中数据的x,k依次为:
9,3;
10,3;
7,4;
10,3;
3,4。
代码实现:
1 #include<cstdio> 2 int n,m,k,x; 3 bool v; 4 void write(bool& v,int x){ 5 if(v) v=false; 6 else putchar(' '); 7 printf("%d",x); 8 } 9 int main(){ 10 while(scanf("%d%d",&n,&m)&&n!=-1){ 11 k=0; 12 for(;k*(k+1)<2*m;k++); 13 x=m-k*(k-1)/2+n-k; 14 v=true; 15 for(int i=1;i<=n-k-1;i++) write(v,i); 16 write(v,x); 17 for(int i=n;i>=n-k;i--) 18 if(i!=x) write(v,i); 19 putchar('\n'); 20 } 21 return 0; 22 }
题目来源:POJ