1. 내용

희소성테이블은 값의 연산 결과를 테이블에 저장해서 빠르게 값의 결과를 찾아가는 문제로 구간합, 구간 최대,최솟값, 중첩함수 문제를 빠른 시간내에 해결이 가능하다.

희소테이블은 언급한 문제들에 따라 다른 값들을 저장하며 문제 풀이에 효율적인 시간을 제공한다.

 

기본적으로 희소테이블은 2차원배열 table[i][j] 이루어진다. 그리고 기본적으로 i+2^(j-1)-1 공식을 이용해서 희소성테이블을 만들 있다.

 

Ex)

구간합 문제

경우에는 table[i][j] 의미하는 것은 배열 arr 주어졌을 arr[i]에서 arr[2^(j-1)-1]까지 구간의 합이 저장되어있다.

임의의 x,y가주어지고 arr배열의 x~y구간까지의 합을 구한다면 y-x 길이에 근접한 [log(y-x)] 가우스 정수 값을 구하고 해당 값은

Table[i][j] 이용해서 O(1) 있다. 그리고 그외 구간은 더해주면 된다.

 

처럼 구간합 뿐만 아니라 각각 f(x) 함수식으로 나타낼 있는 최소, 최대 중첩 함수 등의 문제에서도 활용이 가능하며 결합법칙의 특징을 이용한 만큼

F(x,y,z) = F(F(x,y),z) = F(x,F(y,z))

공식이 성립하는 조건이 존재한다.

 

2. 구현

알고리즘의 구현에 앞서 희소성 테이블은 2 거듭제곱을 이용한 i+2^(j-1)-1 핵심 공식이다.

다시 말해 i j값을 바탕으로 희소성 테이블을 만드는 초기화 작업이 필요하다. I arr배열의 길이 길이를 N이라할

0 <= i <= N-1

된다. 그리고 j값은 N log(2 거듭제곱)으로 했을 가우스 값으로 얻은 logN보다 작으면서 가장 정수 값을 최대 값으로 가진다.

0 <= j <= [logN]

 

위와 같은 범위를 바탕으로 희소성테이블을 만들 있고 희소성 테이블을 만들 때는 재귀를 이용해서 빠르게 구할 있다.

 

3. 알고리즘

      • 백준(합성함수와 쿼리)

#include<iostream>

#include<cmath>

 

using namespace std;

 

int arr[200001];

int table[200001][20];

 

void query(int n, int& x,int log_n) {

while (log_n != 0 && n>0) {

log_n = (int)(log(n)/log(2));

x = table[x][log_n];

n -= pow(2, log_n);

}

}

int main(void) {

int M,buf,Q,buf2;

cin >> M;

for (int i = 0; i < M; i++) {

cin >> buf;

arr[i] = buf;

table[i][0] = buf;

}

for (int j = 1; j < 19; j++) {

for (int i = 0; i < M; i++) {

table[i][j] = table[table[i][j - 1]-1][j - 1];

}

}

cin >> Q;

for (int i = 0; i < Q; i++) {

cin >> buf >> buf2;

int log_n = 1;

buf2 -= 1;

query(buf, buf2,log_n);

cout << buf2 << endl;

}

return 0;

}

 

 

+ Recent posts