https://ac.nowcoder.com/acm/contest/33187/G
题意
找到数列 [1, 2, …, n] 的一种排列,使得
m
a
x
(
l
i
s
(
p
)
,
l
d
s
(
p
)
)
max(lis(p),lds(p))
max(lis(p),lds(p)) 最小。
l
i
s
(
p
)
,
l
d
s
(
p
)
lis(p),\ lds(p)
lis(p), lds(p) 分别指 最长上升子序列 和 最长下降子序列的长度。
1 ≤ n ≤ 1 0 6 1≤n≤10^6 1≤n≤106
思路
打表发现,可以将所有数分成
⌈
n
⌉
\left\lceil \sqrt n \right\rceil
⌈n⌉ 块,把所有块倒着放,每一块中的数递增,如:789 456 123
,或者这样 321 654 987
。
m a x ( l i s ( p ) , l d s ( p ) ) max(lis(p),lds(p)) max(lis(p),lds(p)) 为 ⌈ n ⌉ \left\lceil \sqrt n \right\rceil ⌈n⌉。
Code
#include<bits/stdc++.h>
using namespace std;
#define Ios ios::sync_with_stdio(false),cin.tie(0)
#define endl '\n'
map<int,int> mp;
const int N = 200010, mod = 1e9+7;
int T, n, m;
int a[N];
signed main(){
Ios;
for(int i=1;i<=1000;i++) mp[i*i] = i;
cin >> T;
while(T--)
{
cin >> n;
int x;
if(mp.count(n)) x = mp[n];
else x = sqrt(n) + 1;
int cnt = 0;
for(int i=1;i<=n;i++)
{
cnt++;
if(cnt == x){
for(int j=i;j>i-x;j--) cout << j << ' ';
cnt = 0;
}
}
if(cnt){
for(int j=n;j>n-cnt;j--) cout << j << ' ';
}
cout << endl;
}
return 0;
}