Cheese: tree section

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;

Guess you like

Origin www.cnblogs.com/loney-s/p/12158092.html