사용 알고리즘
Greedy-Style Constructive
풀이
문제를 아주 짧게 요약하면 다음과 같다.
N, K (<=10^6)이 주어질때, max(LIS길이, LDS길이) = k인 길이 N의 순열을 아무거나 출력한다.
하나에만 초점을 맞추자. 여기서는 LDS에 초점을 맞추겠다.
LDS가 정확히 k이려면 어떻게 순열을 구성해야 할까?
위처럼 연속된 K개의 값이 감소하게 이루어지면 된다.
그렇다면 LDS<K+1이 되게 하려면 어떻게 구성해야 할까? 정답은 A+1 뒤에 A+1 미만의 값이 없으면 된다.
이렇게 하면서 LIS<K+1이 되게 하려면 어떻게 구성해야 할까?
이렇게 구성하면 LIS는 크기 K인(정확히는 K 이하) 각 그룹에서 하나씩밖에 선택될 수 없다. 따라서 이러한 그룹의 개수가 LIS의 길이이고, 그 길이가 K 이하이면 된다.
크기 K인 각 그룹의 개수가 K개 이하여야 하므로, K*K<N이면 불가능함을 알 수 있고, 그 외의 경우에는 위와 같이 답을 구성하면 된다.
#include <iostream>
#include <cmath>
#include <algorithm>
#include <numeric>
#include <cstring>
#include <vector>
#include <string>
#include <climits>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <bitset>
#include <cassert>
#include <list>
using namespace std;
typedef long long ll;
#define fast ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0)
#define all(x) x.begin(), x.end()
#define rll(x) x.rbegin(), x.rend()
#define comp(x) x.erase(unique(all(x)), x.end())
#define MOD 1000000009
ll n, k;
int main(){
fast;
cin>>n>>k;
if(k*k<n)return cout<<-1, 0;
ll cur = k;
vector<ll> ans(n+1, 0);
ll cnt = 1;
ll cnt2 = 0;
for(int i = 1 ; i <= n ; i++){
ans[i]=cur--;
if(++cnt2==k){
cnt++;
cnt2=0;
cur = min(n,k*cnt);
}
}
for(int i = 1 ; i <= n ; i++)cout<<ans[i]<<" ";
}
이 풀이를 확장하면 P3인 NMK (https://www.acmicpc.net/problem/1201)을 풀 수 있다.
퍼솔 냠
'백준 > 골드' 카테고리의 다른 글
solve G5~G1 (1) (0) | 2023.08.01 |
---|---|
BOJ 16964 - DFS 스페셜 저지 (G3) (0) | 2023.07.21 |
BOJ 2613 - 숫자구슬 (G2) (0) | 2023.07.11 |