Link with Monotonic Subsequence(分块,思维)

文章讨论了一个关于计算给定长度排列中,其最长递增子序列和最长递减子序列长度之和最小的排列问题。作者提出了一种解决方案,利用sqrt(n)的特性划分并确定排列结构。
摘要由CSDN通过智能技术生成

First, let's review some definitions. Feel free to skip this part if you are familiar with them.

A sequence aaa is an increasing (decreasing) subsequence of a sequence bbb if aaa can be obtained from bbb by deletion of several (possibly, zero or all) elements and all elements are in increasing (decreasing) order from the beginning to the end.

A permutation is an array consisting of nnn distinct integers from 111 to nnn in arbitrary order. For example, [2,3,1,5,4][2,3,1,5,4][2,3,1,5,4] is a permutation, but [1,2,2][1,2,2][1,2,2] is not a permutation (222 appears twice in the array) and [1,3,4][1,3,4][1,3,4] is also not a permutation (n=3n=3n=3 but there is 444 in the array).

The problem starts from here.

Link has an array. He is currently learning the longest increasing subsequence algorithm. So he comes up with the following question.

Let the value of a permutation ppp be max⁡(lis(p),lds(p))\max({\rm lis}(p),{\rm lds}(p))max(lis(p),lds(p)), where lis(p){\rm lis}(p)lis(p) is the length of the longest increasing subsequence of ppp and lds(p){\rm lds}(p)lds(p) is the length of the longest decreasing subsequence of ppp. For all permutations of length nnn, which one has the minimum value?
 

输入描述:

 

Each test contains multiple test cases. The first line contains the number of test cases T(1≤T≤1000)T(1\le T \le1000)T(1≤T≤1000).

For each test case, there is only one line, containing an integer n(1≤n≤106)n(1 \leq n \leq 10^6)n(1≤n≤106).

It is guaranteed that the sum of nnn over all test cases does not exceed 10610^6106.

输出描述:

 

For each test case, output a single line containing a permutation of length nnn.

If there are multiple answers, print any of them.

示例1

输入

复制3 1 2 3

3
1
2
3

输出

复制1 1 2 1 3 2

1
1 2
1 3 2

思路:

1,打表,找到符合题意的解,发现value和sqrt(n)有关

2,3 2 1 6 5 4 9 8 7,这样的话,分sqrt(n)块,块内减,块间递增,value是sqrt(n)。

代码:

void solve(){
    int n;cin>>n;
    int cnt=ceil(sqrt(n));
    vector<int>ve;
    int now=cnt,pre=1;
    rep(i,1,n){
        ve.emplace_back(now--);
        if(ve.size()==cnt){
            for(auto j:ve)cout<<j<<' ';
            ve.clear();
            now=min(++pre*cnt,n);
        }
    }
    for(auto i:ve)cout<<i<<' ';
    cout<<'\n';
    
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值