주간이 아닌 회고록에 쓰던 문제들을 문제 단위로 나눠서 올리게 될거 같습니다. 이유는 몰아서 쓰다 보니 좀 힘든 감도 있었고. 짧게라도 자주 쓰는 습관을 들이고 싶은거도 있고. 분량이 너무 긴가? 에 대한 스트레스도 안 받아도 되고.
팀 연습 하다가 만난 문제인데 셋에서 업솔빙 한 문제중 유일하게 마음에 드는 문제였네요.
k번째로 작은 값이 들어 갈 수 있는 정점에 대해 두가지 성질을 관찰 해야 합니다. 편의를 위해 모든 값이 unique하다고 가정합시다.
- 루트의 깊이를 1이라 했을 때, 깊이가 k이하여야 한다. (어떤 정점의 조상들에 속한 값은 전부 그 정점에 속한 값보다 작아야 하기 때문)
- 그 정점을 루트로 하는 서브트리의 크기를 s라 했을때 s−1≤n−k를 만족해야 한다. (서브트리에 속한 값들이 자기 자신을 제외하면 전부 자신보다 작아야 하기 때문)
따라서 위 두 조건을 만족하는 정점의 개수를 찾아주면 됩니다. 깊이 k이하인 정점들 중 답이 될 수 없는 정점의 개수를 x, 깊이 k이하인 모든 정점의 개수를 z라 하면 답은 z−x가 됩니다. 다만 단순히 모든 정점을 확인하면 너무 느리기 때문에 한 가지 관찰을 더 해줘야 합니다.
- 정점 번호가 증가함에 따라 그 정점을 루트로 하는 서브트리의 크기는 단조 감소한다.
따라서 우리는 x를 이진 탐색으로 구할 수 있습니다. 하지만 여기서 한가지 구현 디테일이 필요한데 바로 i번 정점을 루트로 하는 서브트리의 정점 개수를 구하는 과정입니다. (실제로 팀 연습 중 이 부분을 못해서 못 풀었습니다.)
L=i,R=i에서 시작해서 L=L×2, R=R×2+1을 L과 R이 n을 넘지 않는 범위 내에서 반복해 나가면 각 단계에서 R−L+1은 그 레벨에서 i번 정점에 속한 서브트리의 정점의 개수입니다. (L은 i에서 왼쪽으로 쭉 뻗어나가고 R은 i에서 오른쪽으로 쭉 뻗어나가는 구조임을 생각해보면 됩니다.) L, R모두 두배씩 늘어남으로 이 단계 또한 O(logN) 시간이 걸림을 알 수 있습니다.
#include <bits/stdc++.h>
#include <ext/rope>
using namespace std;
using namespace __gnu_cxx;
#pragma GCC optimize("O3")
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#define endl '\n'
#define PRECISION 69
#define fr first
#define sc second
#define all(v) v.begin(), v.end()
#define compress(v) sort(all(v)), v.erase(unique(all(v)), v.end())
using ll = long long;
using ld = long double;
typedef pair<ll,ll> pll;
typedef pair<int,int> pii;
const int INF = 0x3f3f3f3f;
const ll LLINF = 4'500'000'000'000'000'000;
const ll MOD = 1'000'000'007;
bool test(ll N, ll K, ll node){
if(node == 0) return 1;
ll L = node, R = node;
ll ret = 0;
while(L <= N) {
ret += min(N, R) - L + 1;
L = L * 2;
R = R * 2 + 1;
}
return ret - 1 > N - K;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.setf(ios::fixed); cout.precision(PRECISION);
ll N, K; cin >> N >> K;
ll l = 0, r = min(N, (1LL << (min(K, 62LL))) - 1);
ll res = 0; ll mx = r;
while(l <= r) {
ll mid = (l + r) / 2;
if(test(N, K, mid)){
res = mid;
l = mid + 1;
} else r = mid - 1;
}
cout << (mx - res);
}
짧은 구현인데도 방법을 못 떠올려서 못 풀었네요. 다시금 구현은 풀이와 발상의 일부라는걸 상기하게 되는 계기였던거 같습니다.
'PS > BOJ' 카테고리의 다른 글
2023.06.24 골랜디 (0) | 2023.06.24 |
---|---|
2023.06.22 양갈래 골랜디 스터디 그룹 (0) | 2023.06.23 |