data_structure/HLD_lazy.hpp
Code
template<typename T,typename E>
class HLD_lazy{
class lazy_segment_tree{
int n=1,sz;
T* node;
E* lazy;
int ids[64];
int idx;
void eval(const auto& t){
if(lazy[t]==ee)return;
node[t]=h(node[t],lazy[t],n>>(int)(log2(t+1)));
if(t<n-1){
lazy[(t<<1)+1]=g(lazy[(t<<1)+1],lazy[t]);
lazy[(t<<1)+2]=g(lazy[(t<<1)+2],lazy[t]);
}
lazy[t]=ee;
}
void get_eval(auto l,auto r){
l+=n;r+=n;
const int lm=(l/(l&-l))>>1;
const int rm=(r/(r&-r))>>1;
idx=0;
while(r>l){
if(r<=rm&&r)ids[idx++]=r-1;
if(l<=lm&&l)ids[idx++]=l-1;
l>>=1;r>>=1;
}
while(l){
ids[idx++]=l-1;
l>>=1;
}
}
public:
lazy_segment_tree(const vector<T>& v):sz(v.size()){
while(n<(int)v.size())n<<=1;
node=new T[(n<<1)-1];
lazy=new E[(n<<1)-1];
for(int i=(int)v.size()+n-1;i<(n<<1)-1;i++)node[i]=et;
for(int i=0;i<(n<<1)-1;i++)lazy[i]=ee;
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]);
}
lazy_segment_tree(const auto& sz):sz(sz){
while(n<(int)sz)n<<=1;
node=new T[(n<<1)-1];
lazy=new E[(n<<1)-1];
for(int i=0;i<(n<<1)-1;i++)node[i]=et;
for(int i=0;i<(n<<1)-1;i++)lazy[i]=ee;
}
void update(auto l,auto r,E val){
if(l>r)swap(l,r);
r++;
get_eval(l,r);
for(int i=idx-1;i>=0;i--)eval(ids[i]);
l+=n;r+=n;
while(l<r){
if(l&1){lazy[l-1]=g(lazy[l-1],val);eval(l-1);++l;}
if(r&1){--r;lazy[r-1]=g(lazy[r-1],val);eval(r-1);}
l>>=1;r>>=1;
}
for(int i=0;i<idx;i++){
eval((ids[i]<<1)+1);
eval((ids[i]<<1)+2);
node[ids[i]]=f(node[(ids[i]<<1)+1],node[(ids[i]<<1)+2]);
}
}
T get(auto l,auto r){
if(l>r)swap(l,r);
r++;
get_eval(l,r);
for(int i=idx-1;i>=0;i--)eval(ids[i]);
l+=n;r+=n;
T res=et;
while(l<r){
if(l&1){eval(l-1);res=f(res,node[l-1]);l++;}
if(r&1){--r;eval(r-1);res=f(res,node[r-1]);}
l>>=1;r>>=1;
}
return res;
}
};
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(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);
stack<tuple<int,int>>stk;
stk.emplace(root,-1);
int idx=0;
par[root]=root;
head[root]=root;
while(!stk.empty()){
int n,p;
tie(n,p)=stk.top();
stk.pop();
vertex[n]=idx++;
int mx=0,heavy=-1;
for(auto t:v[n])if(t!=p&&mx<sz[t]){
mx=sz[t];
heavy=t;
}
for(auto t:v[n]){
if(t!=heavy&&t!=p){
par[t]=n;
head[t]=t;
stk.emplace(t,n);
}
}
if(heavy!=-1){
par[heavy]=par[n];
head[heavy]=head[n];
stk.emplace(heavy,n);
}
}
}
int* sz;
int* vertex;
int* par;
int* head;
lazy_segment_tree* seg;
public:
HLD_lazy(const auto& v,int root=0){
make(v,root);
seg=new lazy_segment_tree(v.size());
}
HLD_lazy(const auto& v,const auto& a,int root=0){
vector<T>tmp(v.size());
make(v,root);
for(int i=0;i<(int)v.size();i++){
tmp[vertex[i]]=a[i];
}
seg=new lazy_segment_tree(tmp);
}
int lca(auto l,auto r){
while(1){
if(head[l]==head[r])return sz[l]>sz[r]?l:r;
else if(sz[head[l]]>sz[head[r]])r=par[r];
else l=par[l];
}
}
inline void update_vertex(auto u,E x){
seg->update(vertex[u],vertex[u],x);
}
inline T get_vertex(auto u){
return seg->get(vertex[u],vertex[u]);
}
inline void update_subtree(auto u,E x){
seg->update(vertex[u],vertex[u]+sz[u]-1);
}
inline T get_subtree(auto u){
return seg->get(vertex[u],vertex[u]+sz[u]-1);
}
void update_path(auto u,auto v,E x){
while(1){
if(head[u]==head[v]){
seg->update(vertex[u],vertex[v],x);
break;
}
else if(sz[head[u]]>sz[head[v]]){
seg->update(vertex[v],vertex[head[v]],x);
v=par[v];
}
else{
seg->update(vertex[u],vertex[head[u]],x);
u=par[u];
}
}
}
T get_path(auto u,auto v){
T res=et;
while(1){
if(head[u]==head[v]){
return f(res,seg->get(vertex[u],vertex[v]));
}
else 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];
}
}
}
protected:
constexpr static T et=0;
constexpr static E ee=0;
constexpr static
T f(const T& a,const T& b){
return a+b;
}
constexpr static
T h(const T& a,const E& b,const auto& sz){
return a+b*sz;
}
constexpr static
E g(const E& a,const E& b){
return a+b;
}
constexpr static
auto update(auto a,auto b){return b==ee?a:b;}
};
#line 1 "data_structure/HLD_lazy.hpp"
template<typename T,typename E>
class HLD_lazy{
class lazy_segment_tree{
int n=1,sz;
T* node;
E* lazy;
int ids[64];
int idx;
void eval(const auto& t){
if(lazy[t]==ee)return;
node[t]=h(node[t],lazy[t],n>>(int)(log2(t+1)));
if(t<n-1){
lazy[(t<<1)+1]=g(lazy[(t<<1)+1],lazy[t]);
lazy[(t<<1)+2]=g(lazy[(t<<1)+2],lazy[t]);
}
lazy[t]=ee;
}
void get_eval(auto l,auto r){
l+=n;r+=n;
const int lm=(l/(l&-l))>>1;
const int rm=(r/(r&-r))>>1;
idx=0;
while(r>l){
if(r<=rm&&r)ids[idx++]=r-1;
if(l<=lm&&l)ids[idx++]=l-1;
l>>=1;r>>=1;
}
while(l){
ids[idx++]=l-1;
l>>=1;
}
}
public:
lazy_segment_tree(const vector<T>& v):sz(v.size()){
while(n<(int)v.size())n<<=1;
node=new T[(n<<1)-1];
lazy=new E[(n<<1)-1];
for(int i=(int)v.size()+n-1;i<(n<<1)-1;i++)node[i]=et;
for(int i=0;i<(n<<1)-1;i++)lazy[i]=ee;
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]);
}
lazy_segment_tree(const auto& sz):sz(sz){
while(n<(int)sz)n<<=1;
node=new T[(n<<1)-1];
lazy=new E[(n<<1)-1];
for(int i=0;i<(n<<1)-1;i++)node[i]=et;
for(int i=0;i<(n<<1)-1;i++)lazy[i]=ee;
}
void update(auto l,auto r,E val){
if(l>r)swap(l,r);
r++;
get_eval(l,r);
for(int i=idx-1;i>=0;i--)eval(ids[i]);
l+=n;r+=n;
while(l<r){
if(l&1){lazy[l-1]=g(lazy[l-1],val);eval(l-1);++l;}
if(r&1){--r;lazy[r-1]=g(lazy[r-1],val);eval(r-1);}
l>>=1;r>>=1;
}
for(int i=0;i<idx;i++){
eval((ids[i]<<1)+1);
eval((ids[i]<<1)+2);
node[ids[i]]=f(node[(ids[i]<<1)+1],node[(ids[i]<<1)+2]);
}
}
T get(auto l,auto r){
if(l>r)swap(l,r);
r++;
get_eval(l,r);
for(int i=idx-1;i>=0;i--)eval(ids[i]);
l+=n;r+=n;
T res=et;
while(l<r){
if(l&1){eval(l-1);res=f(res,node[l-1]);l++;}
if(r&1){--r;eval(r-1);res=f(res,node[r-1]);}
l>>=1;r>>=1;
}
return res;
}
};
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(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);
stack<tuple<int,int>>stk;
stk.emplace(root,-1);
int idx=0;
par[root]=root;
head[root]=root;
while(!stk.empty()){
int n,p;
tie(n,p)=stk.top();
stk.pop();
vertex[n]=idx++;
int mx=0,heavy=-1;
for(auto t:v[n])if(t!=p&&mx<sz[t]){
mx=sz[t];
heavy=t;
}
for(auto t:v[n]){
if(t!=heavy&&t!=p){
par[t]=n;
head[t]=t;
stk.emplace(t,n);
}
}
if(heavy!=-1){
par[heavy]=par[n];
head[heavy]=head[n];
stk.emplace(heavy,n);
}
}
}
int* sz;
int* vertex;
int* par;
int* head;
lazy_segment_tree* seg;
public:
HLD_lazy(const auto& v,int root=0){
make(v,root);
seg=new lazy_segment_tree(v.size());
}
HLD_lazy(const auto& v,const auto& a,int root=0){
vector<T>tmp(v.size());
make(v,root);
for(int i=0;i<(int)v.size();i++){
tmp[vertex[i]]=a[i];
}
seg=new lazy_segment_tree(tmp);
}
int lca(auto l,auto r){
while(1){
if(head[l]==head[r])return sz[l]>sz[r]?l:r;
else if(sz[head[l]]>sz[head[r]])r=par[r];
else l=par[l];
}
}
inline void update_vertex(auto u,E x){
seg->update(vertex[u],vertex[u],x);
}
inline T get_vertex(auto u){
return seg->get(vertex[u],vertex[u]);
}
inline void update_subtree(auto u,E x){
seg->update(vertex[u],vertex[u]+sz[u]-1);
}
inline T get_subtree(auto u){
return seg->get(vertex[u],vertex[u]+sz[u]-1);
}
void update_path(auto u,auto v,E x){
while(1){
if(head[u]==head[v]){
seg->update(vertex[u],vertex[v],x);
break;
}
else if(sz[head[u]]>sz[head[v]]){
seg->update(vertex[v],vertex[head[v]],x);
v=par[v];
}
else{
seg->update(vertex[u],vertex[head[u]],x);
u=par[u];
}
}
}
T get_path(auto u,auto v){
T res=et;
while(1){
if(head[u]==head[v]){
return f(res,seg->get(vertex[u],vertex[v]));
}
else 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];
}
}
}
protected:
constexpr static T et=0;
constexpr static E ee=0;
constexpr static
T f(const T& a,const T& b){
return a+b;
}
constexpr static
T h(const T& a,const E& b,const auto& sz){
return a+b*sz;
}
constexpr static
E g(const E& a,const E& b){
return a+b;
}
constexpr static
auto update(auto a,auto b){return b==ee?a:b;}
};
Back to top page