Tree - GitDeveloperKim/DreamEach GitHub Wiki
- ํธ๋ฆฌ๋ ๋ ธ๋ N๊ฐ์ ๊ฐ์ N-1๊ฐ๋ก ์ด๋ฃจ์ด์ง ์ฌ์ดํด ์๋ ์ฐ๊ฒฐ ๊ทธ๋ํ๋ฅผ ๋งํ๋ค
- ๋ฃจํธ ๋ ธ๋ : ๋ถ๋ชจ๊ฐ ์๋ ์ต์์ ๋ ธ๋
- ๋จ๋ง ๋ ธ๋ : ์์์ด ์๋ ๋ ธ๋
- ํฌ๊ธฐ : ํธ๋ฆฌ์ ํฌํจ๋ ๋ชจ๋ ๋ ธ๋์ ๊ฐ์
- ๊น์ด : ๋ฃจํธ ๋ ธ๋๋ถํฐ์ ๊ฑฐ๋ฆฌ
- ๋์ด : ๊น์ด ์ค ์ต๋๊ฐ
- ์ฐจ์ : ๊ฐ ๋ ธ๋์ ๊ฐ์ ๊ฐ์
- ๋ถ๋ชจ๋ ธ๋ : N
- ์์ ๋ ธ๋ : Nx2, Nx2+1
- ์์ ๋ ธ๋ -> ๋ถ๋ชจ๋ ธ๋ : N/2
- ํ์ํ ๋ ธ๋์ ๊ฐ์ 2^(h+1) +1 or ๋ณดํต 4*N์ด๋ฉด ์ปค๋ฒ ๊ฐ๋ฅ (์ข ๋ง๋ถ)
- ํธ๋ฆฌ์ ๋์ด logN
- ๋ฌธ์ ํ์ด
- ํธ๋ฆฌ์ ์ง๋ฆ์ ๋ ๋ ธ๋ ๊ฐ ๊ฒฝ๋ก์ ๊ธธ์ด ์ค ์ต๋๊ฐ์ด๋ค.
- ์ฒซ๋ฒ์งธ ๋ฐฉ๋ฒ, ์์์ ๋ ธ๋๋ฅผ ๋ฃจํธ๋ก ์ง์ ํ ๋ค์ ๊ฐ ์๋ธํธ๋ฆฌ์ ๋ํด ๋ฐ๋ก๋ฐ๋ก ๋ฌธ์ ๋ฅผ ํผ๋ค
- ๋๋ฒ์งธ ๋ฐฉ๋ฒ, ๊น์ด ์ฐ์ ํ์์ ๋๋ฒ ์งํ
- TBD
- ์ต์ ๊ณตํต ์กฐ์ ๋ฌธ์ ๋ ๋ ๋ ธ๋์ ๊ณตํต๋ ์กฐ์ ์ค์์ ๊ฐ์ฅ ๊ฐ๊น์ด ์กฐ์์ ์ฐพ๋ ๋ฌธ์
- ArrayList : ์ ๋ ฅ๊ฐ ์ ์ ๋ค์ ์ ๋ณด
- parent[] : ๋์ ๋ถ๋ชจ ์ ์
- depth[] : ๋์ ๊น์ด
- ๋ฃจํธ๋ ธ๋(1)๊ฐ ์ ํด์ง๋ฉด ๊ฐ ๋ ธ๋์ Depth ๋ฅผ ๊ธฐ๋กํ ์ ์๋ค -> DFS ์ด์ฉ
- ๋งค ์ฟผ๋ฆฌ๋ง๋ค ๋ถ๋ชจ ๋ฐฉํฅ์ผ๋ก ๊ฑฐ์ฌ๋ฌ ์ฌ๋ผ๊ฐ๊ธฐ ์ํด ์ต์ ์ ๊ฒฝ์ฐ O(N)์ ์๊ฐ ๋ณต์ก๋, ์ฆ ๋ชจ๋ ์ฟผ๋ฆฌ ์ฒ๋ฆฌ ์๊ฐ ๋ณต์ก๋ O(NM)
- ๋ฐฑ์ค 3584
static int solve(int a, int a_depth, int b, int b_depth){
// ๋์ depth๊ฐ ๊ฐ์์ง ๋๊น์ง ์๋ก ์ฌ๋ฆฐ๋ค.
if(a_depth > b_depth){
while(a_depth != b_depth){
a_depth--;
a = parent[a];
}
}
else if(a_depth < b_depth){
while(a_depth != b_depth){
b_depth--;
b = parent[b];
}
}
// ๋์ ๋ถ๋ชจ๊ฐ์ด ๊ฐ์์ง ๋๊น์ง ์๋ก ์ฌ๋ฆฐ๋ค
while(a != b){
a = parent[a];
b = parent[b];
}
return a;
}
- ์ถ์ฒ click
- LCA ๋ก์ง์์ ๋ถ๋ชจ๋ฅผ ๋ฐ๋ก์ ํ๋์ฉ ๊ฒ์ํ์ง ์๊ณ 2^i ์ง์์น์ผ๋ก ์ฌ๋ผ๊ฐ๋ฉด์ ๋น๊ต๋ฅผ ํ๋ฉด ์๋๊ฐ ์ข์์ง๋ค?
- sparse table ํ์ธ ํ์ click
- Sparse Table ์์ ์ ํ์ ์๊ธฐ: arr[i][j] = arr[ arr[i][j-1] ][j-1]
- j ๊ฐ์ ์ด log2(๋ ธ๋ ์) ๋ก ๊ณ์ฐ
- ์ด 15์นธ ์ฌ๋ผ๊ฐ์ผ ํ๋ค๋ฉด (8์นธ -> 4์นธ -> 2์นธ -> 1์นธ)
- ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์กฐ๊ธ ๋ ์ฌ์ฉํ์ฌ ๊ฐ ๋ ธ๋์ ๋ํ์ฌ 2^i ๋ฒ ๋ถ๋ชจ์ ๋ํ ์ ๋ณด๋ฅผ ๊ธฐ๋ก / ์๊ฐ๋ณต์ก๋ O(MlogN)
- ๋ฐฑ์ค 11438 lca2
//find_depth(1,1) ๋ฃจํธ๊ฐ 1๋ฒ ๋
ธ๋, ๊น์ด 1
public static void find_depth (int from, int depth) {
d[from] = depth;
for (int i = 0; i < mat[from].size(); i++) {
int to = mat[from].get(i);
if (d[to] == 0) {
parent[to][0] = from; // ๊ธฐ์ ๋ฐฐ์ด ์์ฑ
find_depth(mat[from].get(i), depth+1);
}
}
}
public static void make_parent ( ) {
for (int j = 1 ; j < k; j++) { // j๋จผ์
for (int i = 1; i<= N; i++) { // i๋ฒ
parent[i][j] = parent[ parent[i][j-1] ] [j-1];// ์ ํ์ ์ ์ฉ
}
}
}
int find_lca(int a, int b) {
if (depth[a] < depth[b]) { // a๊ฐ ๋ ๊น์ ๋
ธ๋๊ฐ ๋๊ฒ
int temp = a;
a = b;
b = temp;
}
// a์ depth๋ฅผ b์ ๋ง์ถ๋ค
int diff = depth[a] - depth[b];
int m = 0;
// ์๋ฅผ ๋ค์ด 13๋งํผ ์ฌ๋ผ๊ฐ์ผ ํ๋ค๋ฉด ์ด๊ฒ์ ์ด์ง์๋ก ํํ, 1101(2)์ด๋ฏ๋ก
// 1์ธ ๊ณณ์ ํ์ํ ๋ ๋ง๋ค sparse ํ
์ด๋ธ์ ๋์ด ๊ฐ์ ์ฆ๊ฐ ์ํค๋ฉด ๋๋ค
while (diff) {
if (diff & 1) {
a = parent[a][m];
}
m++;
diff /= 2;
}
int lca;
// a์ b๊ฐ ๊ฐ๋ค๋ฉด ๊ทธ๊ฒ์ด lca
if (a == b) {
lca = a;
} else {
for (int k = 15; k >= 0; k--) {
if (parent[a][k] != parent[b][k]) {
a = parent[a][k];
b = parent[b][k];
}
}
lca = parent[a][0];
}
return lca;
}
์ถ์ฒ click
- ๋ค์ฐจ์ ์ธ๊ทธ๋จผํธ ํธ๋ฆฌ
- ์ธ๊ทธ๋จผํธ ํธ๋ฆฌ with lazy propagation
- ์ธ๊ทธ๋จผํธ ํธ๋ฆฌ with dynamic
- ์ธ๊ทธ๋จผํธ ํธ๋ฆฌ with Persistent segment tree
- bottom up ๊ตฌํ
- top down ๊ตฌํ
- ๋ฐฑ์ค ์ด๋ก ์ค๋ช click
๋ฌธ์ ํ์ด ๋ฐฑ์ค2042
์ธ๊ทธ๋จผํธ ํธ๋ฆฌ ์์ฑ ์๋์ฝ๋
- ํธ๋ฆฌ์ ํฌ๊ธฐ๋ฅผ ๊ตฌํ๋ ์๋ฆฌ click
tree = new int [1 << (my_log(200_0000)+1)]; // 200_0000 ๋ฆฌํ๋
ธ๋์ ์ต๋๊ฐฏ์
static long init (int node, int start, int end) {
if (start == end) {
// leaf node
return tree[node] = array[start];
} else {
// not leaf node
return tree[node] = init (node*2, start, (start+end)/2) + init (node*2+1, (start+end)/2+1, end); // init left child node and right child node
}
}
๊ตฌ๊ฐํฉ ๊ตฌํ๊ธฐ ์๋์ฝ๋ left right ๊ฐ ์ฐพ์์ผ ํ๋ ๊ตฌ๊ฐ, start, end๊ฐ ํ์ ๊ตฌ๊ฐ
static long sum (int node, int start, int end, int left, int right) {
if (left > end || right < start) {
return 0;
}
if (left <= start && end <= right) {
return tree[node];
}
return sum (node*2, start, (start+end)/2, left, right) + sum (node*2+1, (start+end)/2+1, end, left, right);
}
์ธ๊ทธ๋จผํธ ํธ๋ฆฌ ์ ๋ฐ์ดํธ ์๋์ฝ๋
static void update (int node, int start, int end, int index, long diff) {
if (index < start || index > end)
return;
tree[node] += diff;
if (start != end) {
update (node*2, start, (start+end)/2, index, diff);
update (node*2+1, (start+end)/2+1, end, index, diff);
}
}
- k๋ฒ์งธ ์ ์ฐพ๊ธฐ
- ์ ์ฒด ๊ฐ์ง์ ์๋ ์๋ฅผ 0์ผ๋ก ์ด๊ธฐํํ์ฌ ๋ฐฐ์ด๋ก ๋ง๋ฌ
- ์ธ๊ทธ๋จผํธ ํธ๋ฆฌ์ ๋ค์ด์จ ํด๋น ์ซ์์ ์ธ๋ฑ์ค(๋ฆฌํ)๋ฅผ 1 ์ฆ๊ฐ ์ํด
- ๊ตฌํด์ผํ๋ k๋ฒ์งธ ์๋ฅผ ๊ตฌ๊ฐํฉ์ ์ด์ฉํด ๊ตฌํจ
- ๋น๊ตํ ๋ ์ผ์ชฝ ์์๊ณผ ๋น๊ตํ๋ค, ์ผ์ชฝ ์์๋ณด๋ค ํฌ๋ฉด ๊ทธ ๊ตฌ๊ฐ์ ํฌํจํ๋ ๊ฒ, ์ผ์ชฝ ๊ตฌ๊ฐํฉ ๊ฐ์ ๋นผ์ฃผ๊ณ ์ค๋ฅธ์ชฝ์ ํ์ํ๋ฉด ๋๋ค
- ์ฐ๋ฆฌ๊ฐ ๊ตฌํด์ผ ํ๋๊ฒ์ 1~N ๊น์ง์ ๊ตฌ๊ฐํฉ์ด K์ธ๋ฐ ๊ทธ ์ซ์ N์ ๊ตฌํ๋ฉด ๋๋ค
public static int kth (int node, int start, int end, int k) {
if (start == end) {
return start; // ์ธ๋ฑ์ค๋ฅผ ๋ฆฌํด
} else {
int mid = (start+end)/2;
// ์ผ์ชฝ ์์ ๋
ธ๋๋ณด๋ค ํ์ฌ๊ฐ์ด ํฌ๊ฑฐ๋ ๊ฐ๋ค๋ฉด ์ฐ์ธก ํ์ํด์ผํจ
if (k > tree[2*node]) {
// (k๊ฐ์ ์ผ์ชฝ ๊ตฌ๊ฐํฉ + ์ค๋ฅธ์ชฝ ๊ตฌ๊ฐํฉ์ด๋ฏ๋ก) ์ค๋ฅธ์ชฝ ๊ตฌ๊ฐ์ ํ์ํ ๋๋ ์ผ์ชฝ ๊ตฌ๊ฐํฉ์ ๋นผ์ค์ผํ๋ค
return kth(2*node+1, mid+1, end, k-tree[node*2]);
}
else // k<= tree[2*node]
{
return kth(2*node, start, mid, k);
}
}
}
- ์ผ๋ฐ ์ธ๊ทธ๋จผํธ์ ๋ฌ๋ฆฌ ๊ตฌ๊ฐ์ ์ฌ๋ฌ๊ฐ ์ ๋ฐ์ดํธ ํด์ค์ผ ํ ๋ ์ ์ฉ
- ex) 0-10 ๋ฐฐ์ด์ด ์์๋ 2-7 ๊ตฌ๊ฐ 1์ฉ ์ฆ๊ฐ, 3-10 ๊ตฌ๊ฐ 1์ฉ ์ฆ๊ฐ
click
๋ฐฑ์ค ์ด๋ก ์ค๋ช click
public ArrayListinit (int left, int right, int pos) { int (left == right) { tree[pos] = new ArrayList<>(); tree[pos].add(arr[left]); return tree[pos]; } int mid = (left + right) /2; ArrayList leftArr = init(left, mid, pos*2); ArrayList rightArr = init(mid+1, right, pos*2+1); return tree[pos] = merge(leftArr, rightArr); }public ArrayList merge(ArrayList leftArr, ArrayList rightArr) { ArrayList returnArr = new ArrayList<>(); int i = 0; int j = 0; leftLen = leftArr.size(); riightLen = rightArr.size(); while(i < leftLen && j < rightLen) { if (leftArr.get(i) <= rightArr.get(i)) { returnArr.add(leftArr.get(i); i++; } else { returnArr.add(rightArr.get(j); j++; } } while (i < leftLen) { returnArr.add(left.get(i); i++; } while (j < rightLen) { returnArr.add(right.get(j); j++; } return returnArr; }
<๊ฐ์>
๊ทธ๋ํ์์ ์ด๋ค ์ ์ u์ ๋ํ ์ํ๊ฐ ์ธ์ ํ ์ ์ v์ ๋ํ ์ํ๋ก ์ ์๋๋ฉฐ ์ฐธ์กฐ ํฌ๋ช
ํ๋ค๋ฉด dp๋ฅผ ์ ์ฉํ ์ ์๋ค.
์ข ๋ ์ฌ์ด ๋ง๋ก, ์ ์ u์ ๋ํ ์ํ๊ฐ ์ธ์ ์ ์ v์ ์ํ๋ฅผ ์ฌ์ฉํด์ ์ ํ์์ด ์ธ์์ง๋ค๋ฉด, dp๋ฅผ ์ ์ฉํ ์ ์๋ค.
ํธ๋ฆฌ์์ ์ข ํน์ํ๊ฒ, ์ ์ u์ ์ํ๊ฐ ์ธ์ ์ ์ v์ ์ํ๋ ๋ฃจํธ์ ์ํ๋ก ์ ์ ๋๋ค๋ฉด dp๋ฅผ ์ ์ฉํ ์ ์๋ค.
์ ์ u๋ฅผ ๋ฃจํธ๋ก ํ๋ ์๋ธํธ๋ฆฌ์ ๋ํ ์ํ๋ฅผ ๋ฌป๋ ๋ฌธ์ ๊ฐ ์์ฃผ ๋์จ๋ค.
dp๋ ๋ณดํต ์ ํ์ผ๋ก ์ด๋ฃจ์ด์ง ๊ณต๊ฐ์์ ์ด๋ฃจ์ด์ก์ง๋ง, ํธ๋ฆฌ๋ ๋น์ ํ ๊ตฌ์กฐ์
๋๋ค. ํธ๋ฆฌ์์ dp๋ฅผ ํ๊ธฐ ์ ์, ํ์ ์์๋ฅผ ๋ฏธ๋ฆฌ ์ ํด์ฃผ๋ ๊ฒ์ด ์ผ๋ฐ์ ์
๋๋ค.
ํ์ ์์๋ฅผ ์ ํ๋ ๊ฒ์ dfs๋ฅผ ๋๋ฉด์ ๋์ค๋ ํธ๋ฆฌ, ์ฆ dfs tree๋ฅผ ๊ธฐ์ค์ผ๋ก ํฉ๋๋ค.
reference
reroot