:heavy_check_mark: DisjointSparseTable
(data_structure/disjoint_sparse_table.hpp)

Verified with

Code

#pragma once
#include<functional>
#include<vector>

/**
 * @brief DisjointSparseTable
 */

template<typename T,typename F=std::plus<T>>
class disjoint_sparse_table{
	T** table;
	T* data;
	int n=1,cnt=0;
	public:
	F f;
	disjoint_sparse_table(const std::vector<T>& v,F f):f(f){init(v);}
	disjoint_sparse_table(const std::vector<T>& v):f(F()){init(v);}
	void init(const std::vector<T>& v){
		while(n<(int)v.size())n<<=1,cnt++;
		table=new T*[cnt];
		for(int i=0;i<cnt;i++){
			table[i]=new T[n]();
		}
		data =new T[n];
		for(int i=0;i<(int)v.size();i++)data[i]=v[i];
		for(int i=0;i<cnt;i++){
			for(int j=0;j<(n>>(i+1));j++){
				const int mid=(j<<(i+1))+(1<<i);
				for(int k=0;k<(1<<i);k++){
					if(k==0){
						if(0<=mid-1&&mid-1<(int)v.size())table[i][mid-1]=v[mid-1];
						if(0<=mid&&mid<(int)v.size())table[i][mid]=v[mid];
					}
					else{
						if(0<=mid-1-k&&mid-1-k<(int)v.size())table[i][mid-1-k]=f(table[i][mid-k],v[mid-1-k]);
						if(0<=mid+k&&mid+k<(int)v.size())table[i][mid+k]=f(table[i][mid+k-1],v[mid+k]);
					}
				}
			}
		}
	}
	T get(int l,int r){
		r--;
		if(l==r)return data[l];
		const int t=31-__builtin_clz((int)(l^r));
		return f(table[t][l],table[t][r]);
	}
};
#line 2 "data_structure/disjoint_sparse_table.hpp"
#include<functional>
#include<vector>

/**
 * @brief DisjointSparseTable
 */

template<typename T,typename F=std::plus<T>>
class disjoint_sparse_table{
	T** table;
	T* data;
	int n=1,cnt=0;
	public:
	F f;
	disjoint_sparse_table(const std::vector<T>& v,F f):f(f){init(v);}
	disjoint_sparse_table(const std::vector<T>& v):f(F()){init(v);}
	void init(const std::vector<T>& v){
		while(n<(int)v.size())n<<=1,cnt++;
		table=new T*[cnt];
		for(int i=0;i<cnt;i++){
			table[i]=new T[n]();
		}
		data =new T[n];
		for(int i=0;i<(int)v.size();i++)data[i]=v[i];
		for(int i=0;i<cnt;i++){
			for(int j=0;j<(n>>(i+1));j++){
				const int mid=(j<<(i+1))+(1<<i);
				for(int k=0;k<(1<<i);k++){
					if(k==0){
						if(0<=mid-1&&mid-1<(int)v.size())table[i][mid-1]=v[mid-1];
						if(0<=mid&&mid<(int)v.size())table[i][mid]=v[mid];
					}
					else{
						if(0<=mid-1-k&&mid-1-k<(int)v.size())table[i][mid-1-k]=f(table[i][mid-k],v[mid-1-k]);
						if(0<=mid+k&&mid+k<(int)v.size())table[i][mid+k]=f(table[i][mid+k-1],v[mid+k]);
					}
				}
			}
		}
	}
	T get(int l,int r){
		r--;
		if(l==r)return data[l];
		const int t=31-__builtin_clz((int)(l^r));
		return f(table[t][l],table[t][r]);
	}
};
Back to top page