K swap operation coj

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");
        }

    }
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值