background
For a tree we need to find the distance between two points, the first reaction of many people is to LCA
However, if the modification does it add? We can only use the tree section
operating
Basic variables
Weight: size of subtree
Heavy Son: that is the most important son,
Light Son: Son not heavy
Heavy chain: heavy chain composed of son
thought
Based on the path of divide and conquer,
With tree line to maintain the heavy chain,
The complexity of the proof
We set the current point u, the parent node of the current point is v
If v u to even the edges of the light side,
This shows that the weight is not the son of v u
It means that the \ (size_v> 2 * size_u \ )
However, the total number of points of a total of n,
So light on a certain side chain up to \ (log_n \) a
Therefore, complexity of up to \ (O (log_n) \)
If v is the weight side to side connected u
Description u heavy son,
Therefore, v u side must be connected to the heavy side
And we said above tree line is used to maintain the heavy chain complexity is \ (O (log_n) \)
Heavy chain constant and light side is connected up to the light side \ (log_n \) item, so a maximum of heavy chain \ (log_n \) Article
The total time complexity is the \ (O (log_nlog_n) \)
board
struct tree_chain_split
{
#define MAXN 100005
struct node
{
int l;
int r;
int lazy;
int val;
}tre[4*MAXN];
void build(int l,int r,int k)
{
tre[k].l=l;
tre[k].r=r;
tre[k].lazy=0;
tre[k].val=0;
if(l==r)
return;
int mid=(l+r)>>1;
build(l,mid,k<<1);
build(mid+1,r,k<<1|1);
}
void pushdown(int k)
{
if(tre[k].lazy==0)
return;
tre[k<<1].lazy+=tre[k].lazy;
tre[k<<1|1].lazy+=tre[k].lazy;
tre[k<<1].val+=tre[k].lazy*(tre[k<<1].r-tre[k<<1].l+1);
tre[k<<1|1].val+=tre[k].lazy*(tre[k<<1|1].r-tre[k<<1|1].l+1);
tre[k].lazy=0;
}
void change_poi(int pos,int k,int add)
{
if(pos>tre[k].r||pos<tre[k].l)
return;
if(tre[k].l==tre[k].r)
{
tre[k].val=tre[k].val+add;
return;
}
pushdown(k);
change_poi(pos,k<<1,add);
change_poi(pos,k<<1|1,add);
tre[k].val=tre[k<<1].val+tre[k<<1|1].val;
}
void change_int(int l,int r,int k,int add)
{
if(l>tre[k].r||tre[k].l>r)
return;
if(l<=tre[k].l&&tre[k].r<=r)
{
tre[k].val=tre[k].val+add*(tre[k].r-tre[k].l+1);
tre[k].lazy=tre[k].lazy+add;
return;
}
pushdown(k);
change_int(l,r,k<<1,add);
change_int(l,r,k<<1|1,add);
tre[k].val=tre[k<<1].val+tre[k<<1|1].val;
}
int query(int l,int r,int k)
{
if(l>tre[k].r||tre[k].l>r)
return 0;
if(l<=tre[k].l&&tre[k].r<=r)
return tre[k].val;
pushdown(k);
return query(l,r,k<<1)+query(l,r,k<<1|1);
}
int cnt;
int w[MAXN];
int fa[MAXN];
int id[MAXN];
int siz[MAXN];
int top[MAXN];
int dep[MAXN];
int wson[MAXN];
vector<int> g[MAXN];
#undef MAXN
void addedge(int u,int v)
{
g[u].push_back(v);
}
void dfs1(int u)
{
siz[u]=1;
dep[u]=dep[fa[u]]+1;
int maxx=-1;
int _ind=0;
for(int i=0;i<g[u].size();i++)
{
int v=g[u][i];
if(v!=fa[u])
{
fa[v]=u;
dfs1(v);
siz[u]+=siz[v];
if(siz[v]>maxx)
{
maxx=siz[v];
_ind=v;
}
}
}
wson[u]=_ind;
}
void dfs2(int u,int top_chain)
{
top[u]=top_chain;
id[u]=++cnt;
change_poi(cnt,1,w[u]);
if(!wson[u])
return;
dfs2(wson[u],top_chain);
for(int i=0;i<g[u].size();i++)
{
int v=g[u][i];
if(v!=fa[u]&&v!=wson[u])
dfs2(v,v);
}
}
void init(int len)
{
cnt=0;
build(1,len,1);
dfs1(rt);
dfs2(rt,rt);
}
void change_int(int x,int y,int add)
{
while(top[x]!=top[y])
{
if(dep[top[x]]>dep[top[y]])
swap(x,y);
change_int(id[top[y]],id[y],1,add);
y=fa[top[y]];
}
if(dep[x]>dep[y])
swap(x,y);
change_int(id[x],id[y],1,add);
}
int query(int x,int y)
{
int ret=0;
while(top[x]!=top[y])
{
if(dep[top[x]]>dep[top[y]])
swap(x,y);
ret=ret+query(id[top[y]],id[y],1);
y=fa[top[y]];
}
if(dep[x]>dep[y])
swap(x,y);
ret=ret+query(id[x],id[y],1);
return ret;
}
void change_rot(int x,int add)
{
change_int(id[x],id[x]+siz[x]-1,1,add);
}
int query_rot(int x)
{
return query(id[x],id[x]+siz[x]-1,1);
}
}tre;