/* 问题是找出逆序数为m的最小n全排列
* 直接暴过去找出第i轮需要第k小数,k = m-(n-1)*(n-2)/2+1 ,当然如果m比较小就k=1了
* 然后用treap找第k小数就可以了。。
* O(nlogn)
* 听说有O(n)的规律。。其实我做这题主要为了找规律。。。结果就这么被我水了过去。。
* 好吧继续找规律
*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;
int result[50001], r;
#define MX 100000
int size, root;
long long n, m;
struct Node
{
int l, r, key, rand_fix;
int countl, countr;
}node[MX];
//left rotate
void l_rot(int &index)
{
int y = node[index].r;
node[index].r = node[y].l;
node[index].countr = node[y].countl;
node[y].l = index;
node[y].countl = node[index].countl + node[index].countr + 1;
index = y;
}
//right rotate
void r_rot(int &index)
{
int y = node[index].l;
node[index].l = node[y].r;
node[index].countl = node[y].countr;
node[y].r = index;
node[y].countr = node[index].countl + node[index].countr + 1;
index = y;
}
void insert(int &index, int nkey)
{
if(index == -1)
{
index = ++size;
node[index].l = node[index].r = -1;
node[index].rand_fix = rand();
node[index].key = nkey;
node[index].countl = node[index].countr = 0;
return ;
}
if(nkey < node[index].key)
{
node[index].countl++;
insert(node[index].l, nkey);
if(node[node[index].l].rand_fix > node[index].rand_fix)
r_rot(index);
}
else
{
node[index].countr++;
insert(node[index].r, nkey);
if(node[node[index].r].rand_fix > node[index].rand_fix)
l_rot(index);
}
}
bool remove(int &index, int nkey)
{
if(index == -1) return false;
if(nkey < node[index].key)
{
node[index].countl--;
return remove(node[index].l, nkey);
}
else if(nkey > node[index].key)
{
node[index].countr--;
return remove(node[index].r, nkey);
}
if(node[index].l == -1 && node[index].r == -1)
index = -1;
else if(node[index].l == -1)
index = node[index].r;
else if(node[index].r == -1)
index = node[index].l;
else
{
if(node[node[index].l].rand_fix < node[node[index].r].rand_fix)
{
l_rot(index);
node[index].countl--;
remove(node[index].l, nkey);
}
else
{
r_rot(index);
node[index].countr--;
remove(node[index].r, nkey);
}
}
return true;
}
int find_value(int nkey, int index)
{
if(node[index].countl + 1 == nkey) return node[index].key;
else if(node[index].countl >= nkey) return find_value(nkey, node[index].l);
else return find_value(nkey-node[index].countl-1,node[index].r);
}
void init()
{
size = root = -1;
for(int i = 1;i <= n;i++) insert(root,i);
}
int main()
{
while(scanf("%lld %lld", &n, &m) && n != -1)
{
init();
for(r = 1;r <= n;r++)
{
long long ii;
long long sum = (n-r)*(n-r-1) / 2;
if(sum >= m) ii = 1;
else { ii = m - sum + 1; m -= ii-1; }
result[r] = find_value((int)ii, root);
remove(root,result[r]);
}
printf("%d", result[1]);
for(int i = 2;i <= n;i++) printf(" %d", result[i]);
printf("\n");
}
}
//贪心法,如果 搞出的东西一定是先由1递增,再由n递减!当然也可以仅由一部分组成
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
using namespace std;
int main()
{
long long n, m;
bool f[50001];
int result[100001], r;
while(scanf("%lld %lld", &n, &m) && n != -1)
{
r = 1;
memset(f,true,sizeof(f));
for(int i = 1;i <= n;i++)
{
long long nxt = (n-i)*(n-i-1)/2;
if(nxt > m)
result[r++] = i;
else
{
result[r++] = (m-nxt)+i;
f[result[r-1]] = false;
break;
}
}
int rr = r-2;
if(rr<1) rr = 1;
for(int i = n;i >= rr;i--)
{
if(f[i]) result[r++] = i;
}
printf("%d", result[1]);
for(int i = 2;i <= n;i++) printf(" %d",result[i]);
printf("\n");
}
}