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.)
                                
                                
                                우수한 개발자 콘텐츠 발견에 전념
                                (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.)
                                
                                
                                우수한 개발자 콘텐츠 발견에 전념
                                (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.)