문제 풀이

[백준] 17435번 합성함수와 쿼리

컴영 2020. 9. 1. 18:25

17435 합성함수와 쿼리


문제


함수 f : {1, 2, ..., m}→{1, 2, ..., m}이 있다. 이때 fn : {1, 2, ..., m}→{1, 2, ..., m}을 다음과 같이 정의하자.

* f1(x) = f(x)

fn+1(x) = f(fn(x))

예를 들어 f4(1) = f(f(f(f(1))))이다.

n과 x가 주어질 때 fn(x)를 계산하는 쿼리를 수행하는 프로그램을 작성하시오.


입력


첫 줄에 정수 m이 주어진다. (1 ≤ m ≤ 200,000)

다음 줄에 f(1), f(2), ..., f(m)이 차례대로 주어진다.

다음 줄에 쿼리의 개수 Q가 주어진다. (1 ≤ Q ≤ 200,000)

다음 Q개의 줄에 각각 정수 n과 x가 주어진다. (1 ≤ n ≤ 500,000; 1 ≤ x ≤ m)


출력


주어지는 n, x마다 fn(x)를 출력한다.



풀이)

LCA 알고리즘 중 dp를 이용한 방법을 사용하면 된다.


int arr[i][j] // x = i, 2^j = n 일때의 fn(x)값


arr[i][j+1] = arr[arr[i][j]][j]



코드)

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
31
32
33
#include <stdio.h>
using namespace std;
 
#define MAX 20
int m, q;
int arr[200001][MAX]; //2^19 = 524,288
int main() {
    scanf("%d"&m);
    for (int i = 1; i <= m; i++) {
        scanf("%d"&arr[i][0]);
    }
    scanf("%d"&q);
 
    for (int k = 0; k < MAX-1; k++) {
        for (int i = 1; i <= m; i++) {
            arr[i][k + 1= arr[arr[i][k]][k];
        }
    }
 
    int n, x;
    while (q--)
    {
        scanf("%d %d"&n, &x);
        for (int i = MAX-1; i >= 0; i--) {
            if ((1 << i) & n) {
                x = arr[x][i];
                n -= 1<<i;
            }
        }
        printf("%d\n", x);
    }
    return 0;
}
cs