Description
最近Mr.Q想要只通过一种操作来对序列进行升序排序,该操作是“交换相邻的两个数”,聪明的Mr.Q总是会选择最优的方法进行操作,也就是说他使用的交换次数是最少的。比如对于对于序列:
2 3 1 4
Mr.Q会使用2次交换操作。
而对于序列:
4 3 2 1
Mr.Q会使用6次交换操作。
请你构造一个1~N的排列,使Mr.Q刚好使用 K 次操作将它按升序完成排序。
Input
第一行一个整数T(T≤50),表示数据组数。
接下来每组输入数据占一行,包含一个非负整数K(0≤K≤10^9),含义如题中描述。
Output
对于每组数据你应该输出2行,假如存在多组方案,输出任意一种即可。
第一行一个整数N(1≤N≤10^5),表示你构造的排列长度。
第二行输出你构造的排列,相邻两个数之间用一个空格隔开,请确保每个数都在你构造的排列中只出现1次,并且都处于范围[1,N]内。
请不要输出多余的空格或数字,否则有可能会WA的。
Sample Input
2
0
6
Sample Output
3
1 2 3
4
4 3 2 1
HINT
和前几天做树状数组有关问题时遇到的逆序数类似,只需要简单的构造就行了,另外注意下输出格式的问题,相邻两数之间用空格隔开,最后一个数后面是没有空格的
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const ll hh=100000;
ll n;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%lld",&n);
if(n<100000)
{
printf("%lld\n",n+1);
printf("%lld",n+1);
for(ll i=1;i<=n;i++)
printf(" %lld",i);
printf("\n");
}
else
{
ll sum=0;
ll count;
for(ll i=100000-1;i>0;i--)
{
if(sum+i<=n)
sum+=i;
else
{
count=i;
break;
}
}
printf("%lld\n",hh);
printf("100000");
for(ll i=100000-1;i>count+1;i--)
printf(" %lld",i);
printf(" %lld",n-sum+1);
for(ll i=1;i<=count+1;i++)
{
if(i==n-sum+1)
continue;
printf(" %lld",i);
}
printf("\n");
}
}
}