티스토리 뷰
문제
알고리즘
HLD
풀이
트리에서 두 노드를 잇는 경로가 존재하는지 묻는 문제입니다. 추가적으로 조건에 따라 간선을 끊어주기도 합니다.
트리에서 부모 노드는 유일합니다. 즉 부모 노드로 가는 간선은 유일하므로 모든 간선은 루트를 제외한 모든 노드들로 표현이 가능합니다. HLD를 통해 트리를 일자 형태인 배열로 나타낸 후, 세그먼트 트리를 이용해 구간의 최솟값을 구하면 경로가 존재함을 알 수 있습니다. 최솟값이 1이라면 경로가 존재, 0이라면 끊어져 있는 것입니다. 간선을 끊을 때, 세그먼트 트리에 0 값을 업데이트하면 됩니다. 세그먼트 트리에 접근할 때는 $idx$배열을 통해 접근해야 함을 유의하도록 합시다
코드
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < n; ++i)
#define REP(i, n) for (int i = 1; i <= n; ++i)
#define FAST \
cin.tie(NULL); \
cout.tie(NULL); \
ios::sync_with_stdio(false)
using namespace std;
const int MAXN = 200001;
int N, M, Q, cnt, len;
vector<int> adj[MAXN];
int top[MAXN], pa[MAXN], sz[MAXN], idx[MAXN], bot[MAXN];
vector<int> tree;
int dfs(int here) {
sz[here] = 1;
for (auto& there : adj[here]) {
if (pa[here] ^ there) {
pa[there] = here;
sz[here] += dfs(there);
int& h = adj[here][0];
if (h == pa[here] || sz[h] < sz[there])
swap(h, there);
}
}
return sz[here];
}
void hld(int here) {
idx[here] = cnt++;
for (auto there : adj[here]) {
if (there ^ pa[here]) {
top[there] = there == adj[here][0] ? top[here] : there;
hld(there);
}
}
}
void update(int i, int v) {
tree[i += len] = v;
i >>= 1;
for (; i > 0; i >>= 1) {
tree[i] = min(tree[i * 2], tree[i * 2 + 1]);
}
}
int query(int l, int r) {
l += len;
r += len;
int ret = 1;
for (; l <= r; l >>= 1, r >>= 1) {
if (l & 1)
ret = min(ret, tree[l++]);
if (!(r & 1))
ret = min(ret, tree[r--]);
}
return ret;
}
int solve(int u, int v) {
int ret = 1;
while (top[u] ^ top[v]) {
if (sz[top[u]] < sz[top[v]])
swap(u, v);
ret = min(ret, query(idx[top[v]], idx[v]));
v = pa[top[v]];
}
if (idx[u] > idx[v])
swap(u, v);
ret = min(ret, query(idx[u] + 1, idx[v]));
return ret;
}
int main() {
FAST;
cin >> N >> Q;
len = pow(2, ceil(log2(N)));
tree.resize(len << 1, 1);
for (int i = 1; i < N; ++i) {
int u;
cin >> u;
--u;
adj[u].emplace_back(i);
adj[i].emplace_back(u);
}
dfs(0);
hld(0);
while (Q--) {
int a, b, c;
cin >> a >> b >> c;
--a, --b;
int val = solve(a, b);
if (val)
cout << "YES\n";
else
cout << "NO\n";
if (c == 1) {
if (val) {
update(idx[a], 0);
} else {
update(idx[b], 0);
}
}
}
return 0;
}
'Algorithm' 카테고리의 다른 글
[백준 2302] 극장 좌석 (0) | 2021.01.22 |
---|---|
[백준 20191] 줄임말 (3) | 2021.01.21 |
[백준 20647] Cowntagion (0) | 2021.01.13 |
[백준 20295] 사탕 배달 (0) | 2021.01.11 |
[백준 15586] Mootube (Gold) (0) | 2021.01.09 |
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- Fenwick
- spring
- Suffix Array
- 동적계획법
- Oracle
- bfs
- 정렬
- string
- SCC
- dijkstra
- 2-SAT
- 세그먼트트리
- hld
- 이분탐색
- implementation
- 트라이
- sweeping
- sorting
- dfs
- 스위핑
- 이분매칭
- knapsack
- union find
- kmp
- 좌표압축
- spring boot
- greedy
- 펜윅트리
- Segment tree
- DP
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
글 보관함