Sparse Table을 아십니까? 나는 알고 있다.
Sparse Table이란?
불변의 수열의 임의의 구간에 대한 최소치/최대치를, 전처리 $O(N\log N)$, 쿼리 마다 $O(1)$ 로 구하는 데이터 구조입니다.
숫자 열의 값이 변경될 수 있다면 SegmentTree를 사용합시다. SegmentTree 기사는 여기입니다.
메커니즘
모든 점을 시작점으로 하여 길이가 2인 구간의 최소값/최대값을 먼저 구해 둡니다. 이것은 $O(N\log N)$ 의 전 계산입니다.
쿼리에 대답할 때는 구간의 길이 이하에서 최대 2의 값을 취하고 구간의 앞쪽과 뒤쪽에 끼워 각각의 최소값을 구합니다.
이제 전체 구간을 덮을 수 있으며 최소값을 구할 수 있습니다.
테이블을 구축하면 이런 느낌이 듭니다.
구간의 길이로부터, 그 이하의 2 해야 할 것을 요구하는 것도 전 계산에 포함해 두면(자), 쿼리 마다 $O(1)$ 가 됩니다.
구현
template<typename T>
class SparseTable {
T** table;
int* logtable;
public:
SparseTable(vector<T> vec) {
int maxlength = 0;
while ((1 << (maxlength + 1)) <= vec.size())maxlength++;
table = new T * [maxlength + 1];
logtable = new int[vec.size() + 1];
rep(i, maxlength + 1) {
table[i] = new T[vec.size()];
rep(j, vec.size() - (1 << i) + 1) {
if (i)table[i][j] = min(table[i - 1][j], table[i - 1][j + (1 << (i - 1))]);
else table[i][j] = vec[j];
}
}
for (int i = 2; i <= vec.size(); i++) {
logtable[i] = logtable[i >> 1] + 1;
}
}
~SparseTable() {
rep(i, maxlength) delete[] table[i];
delete[] table;
delete[] logtable;
}
T query(int l, int r) {
assert(l < r);
int length = r - l;
return min(table[logtable[length]][l], table[logtable[length]][r - (1 << logtable[length])]);
}
};
꽤 복잡하고 가독성이 낮습니다. 죄송합니다.
결론
Segment Tree 쪽이 자신으로서는 쓰는 것이 편합니다만, Sparse Table는 정수배가 꽤 가볍습니다.
Sparse Table도 확실히 쓸 수 있도록 해 두면 좋을지도 모릅니다. (사용한 적은 없습니다)
Reference
이 문제에 관하여(Sparse Table을 아십니까? 나는 알고 있다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/ageprocpp/items/e698e11185762a50e412
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
모든 점을 시작점으로 하여 길이가 2인 구간의 최소값/최대값을 먼저 구해 둡니다. 이것은 $O(N\log N)$ 의 전 계산입니다.
쿼리에 대답할 때는 구간의 길이 이하에서 최대 2의 값을 취하고 구간의 앞쪽과 뒤쪽에 끼워 각각의 최소값을 구합니다.
이제 전체 구간을 덮을 수 있으며 최소값을 구할 수 있습니다.
테이블을 구축하면 이런 느낌이 듭니다.
구간의 길이로부터, 그 이하의 2 해야 할 것을 요구하는 것도 전 계산에 포함해 두면(자), 쿼리 마다 $O(1)$ 가 됩니다.
구현
template<typename T>
class SparseTable {
T** table;
int* logtable;
public:
SparseTable(vector<T> vec) {
int maxlength = 0;
while ((1 << (maxlength + 1)) <= vec.size())maxlength++;
table = new T * [maxlength + 1];
logtable = new int[vec.size() + 1];
rep(i, maxlength + 1) {
table[i] = new T[vec.size()];
rep(j, vec.size() - (1 << i) + 1) {
if (i)table[i][j] = min(table[i - 1][j], table[i - 1][j + (1 << (i - 1))]);
else table[i][j] = vec[j];
}
}
for (int i = 2; i <= vec.size(); i++) {
logtable[i] = logtable[i >> 1] + 1;
}
}
~SparseTable() {
rep(i, maxlength) delete[] table[i];
delete[] table;
delete[] logtable;
}
T query(int l, int r) {
assert(l < r);
int length = r - l;
return min(table[logtable[length]][l], table[logtable[length]][r - (1 << logtable[length])]);
}
};
꽤 복잡하고 가독성이 낮습니다. 죄송합니다.
결론
Segment Tree 쪽이 자신으로서는 쓰는 것이 편합니다만, Sparse Table는 정수배가 꽤 가볍습니다.
Sparse Table도 확실히 쓸 수 있도록 해 두면 좋을지도 모릅니다. (사용한 적은 없습니다)
Reference
이 문제에 관하여(Sparse Table을 아십니까? 나는 알고 있다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/ageprocpp/items/e698e11185762a50e412
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
template<typename T>
class SparseTable {
T** table;
int* logtable;
public:
SparseTable(vector<T> vec) {
int maxlength = 0;
while ((1 << (maxlength + 1)) <= vec.size())maxlength++;
table = new T * [maxlength + 1];
logtable = new int[vec.size() + 1];
rep(i, maxlength + 1) {
table[i] = new T[vec.size()];
rep(j, vec.size() - (1 << i) + 1) {
if (i)table[i][j] = min(table[i - 1][j], table[i - 1][j + (1 << (i - 1))]);
else table[i][j] = vec[j];
}
}
for (int i = 2; i <= vec.size(); i++) {
logtable[i] = logtable[i >> 1] + 1;
}
}
~SparseTable() {
rep(i, maxlength) delete[] table[i];
delete[] table;
delete[] logtable;
}
T query(int l, int r) {
assert(l < r);
int length = r - l;
return min(table[logtable[length]][l], table[logtable[length]][r - (1 << logtable[length])]);
}
};
Segment Tree 쪽이 자신으로서는 쓰는 것이 편합니다만, Sparse Table는 정수배가 꽤 가볍습니다.
Sparse Table도 확실히 쓸 수 있도록 해 두면 좋을지도 모릅니다. (사용한 적은 없습니다)
Reference
이 문제에 관하여(Sparse Table을 아십니까? 나는 알고 있다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/ageprocpp/items/e698e11185762a50e412텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)