This documentation is automatically generated by online-judge-tools/verification-helper
View the Project on GitHub ningenMe/compro-library
/* * @title DisjointSparseTable * @docs md/static-range-query/DisjointSparseTable.md */ template<class Operator> class DisjointSparseTable{ public: using TypeNode = typename Operator::TypeNode; size_t depth; size_t length; vector<TypeNode> node; vector<size_t> msb; DisjointSparseTable(const vector<TypeNode>& vec) { for(depth = 0;(1<<depth)<=vec.size();++depth); length = (1<<depth); //msb msb.resize(length,0); for(int i = 0; i < length; ++i) for(int j = 0; j < depth; ++j) if(i>>j) msb[i] = j; //init value node.resize(depth*length,Operator::unit_node); for(int i = 0; i < vec.size(); ++i) node[i] = vec[i]; for(int i = 1; i < depth; ++i) { for(int r = (1<<i),l = r-1; r < length; r += (2<<i),l = r-1){ //init accumulate node[i*length+l] = node[l]; node[i*length+r] = node[r]; //accumulate for(int k = 1; k < (1<<i); ++k) { node[i*length+l-k] = Operator::func_fold(node[i*length+l-k+1],node[l-k]); node[i*length+r+k] = Operator::func_fold(node[i*length+r+k-1],node[r+k]); } } } } //[l,r) TypeNode fold(int l,int r) { r--; return (l>r||l<0||length<=r) ? Operator::unit_node: (l==r ? node[l] : Operator::func_fold(node[msb[l^r]*length+l],node[msb[l^r]*length+r])); } }; //sum template<class T> struct NodeSum { using TypeNode = T; inline static constexpr TypeNode unit_node = 0; inline static constexpr TypeNode func_fold(TypeNode l,TypeNode r){return l+r;} };
#line 1 "lib/13-static-range-query/DisjointSparseTable.cpp" /* * @title DisjointSparseTable * @docs md/static-range-query/DisjointSparseTable.md */ template<class Operator> class DisjointSparseTable{ public: using TypeNode = typename Operator::TypeNode; size_t depth; size_t length; vector<TypeNode> node; vector<size_t> msb; DisjointSparseTable(const vector<TypeNode>& vec) { for(depth = 0;(1<<depth)<=vec.size();++depth); length = (1<<depth); //msb msb.resize(length,0); for(int i = 0; i < length; ++i) for(int j = 0; j < depth; ++j) if(i>>j) msb[i] = j; //init value node.resize(depth*length,Operator::unit_node); for(int i = 0; i < vec.size(); ++i) node[i] = vec[i]; for(int i = 1; i < depth; ++i) { for(int r = (1<<i),l = r-1; r < length; r += (2<<i),l = r-1){ //init accumulate node[i*length+l] = node[l]; node[i*length+r] = node[r]; //accumulate for(int k = 1; k < (1<<i); ++k) { node[i*length+l-k] = Operator::func_fold(node[i*length+l-k+1],node[l-k]); node[i*length+r+k] = Operator::func_fold(node[i*length+r+k-1],node[r+k]); } } } } //[l,r) TypeNode fold(int l,int r) { r--; return (l>r||l<0||length<=r) ? Operator::unit_node: (l==r ? node[l] : Operator::func_fold(node[msb[l^r]*length+l],node[msb[l^r]*length+r])); } }; //sum template<class T> struct NodeSum { using TypeNode = T; inline static constexpr TypeNode unit_node = 0; inline static constexpr TypeNode func_fold(TypeNode l,TypeNode r){return l+r;} };