data_structure/HLD_seg.hpp
Code
template<typename T>
class HLD_seg{
class segment{
T* node;
int n=1;
public:
segment(int sz){
while(n<sz)n<<=1;
node=new T[(n<<1)-1];
for(int i=0;i<(n<<1)-1;i++)node[i]=e;
}
segment(const vector<T>& v){
while(n<(int)v.size())n<<=1;
node=new T[(n<<1)-1];
for(int i=0;i<(int)v.size();i++)node[i+n-1]=v[i];
for(int i=n-2;i>=0;i--)node[i]=f(node[(i<<1)+1],node[(i<<1)+2]);
}
T get(auto l,auto r){
if(l>r)swap(l,r);
l+=n;r+=n+1;
T s=e;
while(l<r){
if(l&1)s=f(s,node[l++-1]);
if(r&1)s=f(s,node[--r-1]);
l>>=1;r>>=1;
}
return s;
}
void update(auto t,T val){
t+=n-1;
while(1){
node[t]=f(node[t],val);
t=(t-1)>>1;
if(!t)break;
}
}
};
int child_size(const auto& v,int n,int p){
int cnt=0;
for(auto t:v[n]){
if(t!=p)cnt+=child_size(v,t,n);
}
return sz[n]=cnt+1;
}
void make_hld(const auto&v,int n,int p){
static int idx=0;
vertex[n]=idx++;
int mx=0,heavy=-1;
for(auto t:v[n])if(t!=p&&mx<sz[t]){
mx=sz[t];
heavy=t;
}
if(heavy!=-1){
par[heavy]=par[n];
head[heavy]=head[n];
make_hld(v,heavy,n);
}
for(auto t:v[n]){
if(t!=heavy&&t!=p){
par[t]=n;
head[t]=t;
make_hld(v,t,n);
}
}
}
int* sz;
int* vertex;
int* par;
int* head;
segment* seg;
public:
HLD_seg(const auto& v,int root=0){
make(v,root);
seg=new segment(v.size());
}
HLD_seg(const auto& v,const auto& a,int root=0){
make(v,root);
vector<T>tmp(v.size());
for(int i=0;i<(int)v.size();i++){
tmp[vertex[i]]=a[i];
}
seg=new segment(tmp);
}
void make(const auto& v,int root){
sz=new int[v.size()];
vertex=new int[v.size()];
par=new int[v.size()];
head=new int[v.size()];
child_size(v,root,-1);
par[root]=root;
head[root]=root;
make_hld(v,root,-1);
}
int lca(auto l,auto r){
while(head[l]!=head[r]){
if(sz[head[l]]>sz[head[r]])r=par[r];
else l=par[l];
}
return sz[l]>sz[r]?l:r;
}
inline void update(auto t,T x){
seg->update(vertex[t],x);
}
T get(auto u,auto v){
T res=e;
while(head[u]!=head[v]){
if(sz[head[u]]>sz[head[v]]){
res=f(res,seg->get(vertex[v],vertex[head[v]]));
v=par[v];
}
else{
res=f(res,seg->get(vertex[u],vertex[head[u]]));
u=par[u];
}
}
return f(res,seg->get(vertex[u],vertex[v]));
}
inline T get_subtree(auto u){
return seg->get(vertex[u],vertex[u]+sz[u]-1);
}
protected:
constexpr static T e=0;
constexpr static
T f(const T& s,const T& t){
return s+t;
}
};
#line 1 "data_structure/HLD_seg.hpp"
template<typename T>
class HLD_seg{
class segment{
T* node;
int n=1;
public:
segment(int sz){
while(n<sz)n<<=1;
node=new T[(n<<1)-1];
for(int i=0;i<(n<<1)-1;i++)node[i]=e;
}
segment(const vector<T>& v){
while(n<(int)v.size())n<<=1;
node=new T[(n<<1)-1];
for(int i=0;i<(int)v.size();i++)node[i+n-1]=v[i];
for(int i=n-2;i>=0;i--)node[i]=f(node[(i<<1)+1],node[(i<<1)+2]);
}
T get(auto l,auto r){
if(l>r)swap(l,r);
l+=n;r+=n+1;
T s=e;
while(l<r){
if(l&1)s=f(s,node[l++-1]);
if(r&1)s=f(s,node[--r-1]);
l>>=1;r>>=1;
}
return s;
}
void update(auto t,T val){
t+=n-1;
while(1){
node[t]=f(node[t],val);
t=(t-1)>>1;
if(!t)break;
}
}
};
int child_size(const auto& v,int n,int p){
int cnt=0;
for(auto t:v[n]){
if(t!=p)cnt+=child_size(v,t,n);
}
return sz[n]=cnt+1;
}
void make_hld(const auto&v,int n,int p){
static int idx=0;
vertex[n]=idx++;
int mx=0,heavy=-1;
for(auto t:v[n])if(t!=p&&mx<sz[t]){
mx=sz[t];
heavy=t;
}
if(heavy!=-1){
par[heavy]=par[n];
head[heavy]=head[n];
make_hld(v,heavy,n);
}
for(auto t:v[n]){
if(t!=heavy&&t!=p){
par[t]=n;
head[t]=t;
make_hld(v,t,n);
}
}
}
int* sz;
int* vertex;
int* par;
int* head;
segment* seg;
public:
HLD_seg(const auto& v,int root=0){
make(v,root);
seg=new segment(v.size());
}
HLD_seg(const auto& v,const auto& a,int root=0){
make(v,root);
vector<T>tmp(v.size());
for(int i=0;i<(int)v.size();i++){
tmp[vertex[i]]=a[i];
}
seg=new segment(tmp);
}
void make(const auto& v,int root){
sz=new int[v.size()];
vertex=new int[v.size()];
par=new int[v.size()];
head=new int[v.size()];
child_size(v,root,-1);
par[root]=root;
head[root]=root;
make_hld(v,root,-1);
}
int lca(auto l,auto r){
while(head[l]!=head[r]){
if(sz[head[l]]>sz[head[r]])r=par[r];
else l=par[l];
}
return sz[l]>sz[r]?l:r;
}
inline void update(auto t,T x){
seg->update(vertex[t],x);
}
T get(auto u,auto v){
T res=e;
while(head[u]!=head[v]){
if(sz[head[u]]>sz[head[v]]){
res=f(res,seg->get(vertex[v],vertex[head[v]]));
v=par[v];
}
else{
res=f(res,seg->get(vertex[u],vertex[head[u]]));
u=par[u];
}
}
return f(res,seg->get(vertex[u],vertex[v]));
}
inline T get_subtree(auto u){
return seg->get(vertex[u],vertex[u]+sz[u]-1);
}
protected:
constexpr static T e=0;
constexpr static
T f(const T& s,const T& t){
return s+t;
}
};
Back to top page