※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※

 

이번에 볼 문제는 백준 30050번 문제인 트리와 쿼리 109이다.
문제는 아래 링크를 확인하자.

https://www.acmicpc.net/problem/30050

 

1번 연산이 있어도 없어도 (루트 노드를 제외한) 모든 노드의 깊이는 초기상태보다 깊어지지 않음을 관찰하자. 한편 입력으로 주어지는 수는 109 이하이므로 많아야 30회 부모 노드 방향으로 이동하면 루트에 도달함을 관찰하면, 주어지는 두 점 사이에는 노드가 많아야 60개정도밖에 없다는 것을 알아낼 수 있다. 한편 쿼리가 10만개밖에 없음을 같이 생각하면, 두 점 사이의 경로에 포함되는 모든 노드를 선형적으로 방문해도 문제를 충분히 해결할 수 있음을  수 있다.

 

1번 연산으로 주어지는 각 노드의 새로운 루트를 map 등의 자료구조로 관리해 LCA를 찾아 문제를 해결하자. 1번 연산이 주어진 적이 없다면 그 노드의 부모는 노드번호를 2로 나눈 몫으로 구할 수 있다.

 

부모노드로 거슬러올라가는 과정에서 노드번호가 항상 감소한다는 점을 이용하면, 두 노드의 번호가 같아질 때까지 번호가 더 큰 노드를 부모 방향으로 거슬러올라가게 하는 것을 반복하는 것으로 두 노드 사이를 잇는 경로를 찾아낼 수 있다.

 

아래는 제출한 소스코드이다.

#include <iostream>
#include <vector>
#include <map>
using namespace std;
typedef long long ll;

int Q;
map<int, int> mp;

int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);

	cin >> Q;
	while (Q--) {
		int q, x, y; cin >> q >> x >> y;
		if (q == 1) {
			if (mp.count(y)) mp[y] = x;
			else mp.insert(make_pair(y, x));
		}
		else {
			ll ans = x + y;
			while (x != y) {
				if (x > y) {
					if (mp.count(x)) x = mp[x];
					else x /= 2;
					ans += x;
				}
				else {
					if (mp.count(y)) y = mp[y];
					else y /= 2;
					ans += y;
				}
			}
			cout << ans - x << '\n';
		}
	}
}
728x90

'BOJ' 카테고리의 다른 글

[BOJ 1490 // C++] 자리수로 나누기  (1) 2024.06.08
[BOJ 20917 // C++] 사회적 거리 두기  (0) 2024.06.07
[BOJ 21278 // C++] 호석이 두 마리 치킨  (0) 2024.06.05
[BOJ 2632 // C++] 피자판매  (0) 2024.06.04
[BOJ 26654 // C++] 원점  (0) 2024.06.03

+ Recent posts