zoukankan      html  css  js  c++  java
  • 树链剖分入门+博客推荐

    树链剖分入门博客推荐

    网上关于树链剖分的文章很多,自己在学习树链剖分的时候找到了几篇好的文章,代码规范,有图例。树链剖分的部分自己先挖个坑,以后再专门写个博客来总结。

    博客推荐

    博客一

    推荐理由:每个函数完成后的结果都有相应的图例,可以自己模拟一下和图对应,加深对函数功能的理解。

    博客二

    推荐理由:完整的函数实现,树链剖分+线段树的完整代码。

    博客三

    推荐理由:代码规范,通俗易懂。

    我的常用代码模板

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int maxn=1e5+7;
    struct node{
        int l, r;
        int ans, lazy;
    }
    struct edge{
        int to, next;
    }e[maxn<<1];
    int head[maxn], len;
    int son[maxn], size[maxn], dep[maxn], fa[maxn];
    int top[maxn], inp[maxn], cnt;
    void init()
    {
        len=cnt=0;
        for(int i=0; i<=n; i++)
            head[i]=-1;
    }
    void add(int u, int v)
    {
        e[len].to=v;
        e[len].next=head[u];
        head[u]=len++;
    }
    
    1. dfs1主要是解决树上点的基本信息
    void dfs1(int u, int f, int depth)
    {
     	size[u]=1;
        dep[u]=pedth;
        fa[u]=f;
        for(int i=head[u]; i!=-1; i=e[i].next)
        {
            int v=e[i].to;
            if(v==f) continue;
            dfs1(v, u, depth+1);
            size[u]+=size[v];
            if(size[v] > size[son[u]])
                son[u]=v;
        }
    }
    
    1. dfs2是处理dfs序和重链
    void dfs2(int u, int tp)
    {
        top[u]=tp;
        in[u]=++cnt;
        if(!son[u])
            return;
        dfs2(son[u], tp);
        for(int i=head[u]; i!=-1; i=e[i].next)
        {
            int v=e[i].to;
            if(v==son[u] || v==f[u])
                continue;
            dfs2(v, v);
        }
    }
    
    1. 处理x和y的最近公共祖先
    //fx表示x所在链的顶,fy表示y所在链的顶。
    void lca(int x, int y)
    {
        int fx=top[x], fy=top[y];
        while(fx!=fy)
        {
            if(dep[fx] < dep[fy]) //确保每次更新都是深度大的都是x
            {
                swap(x, y);
                swap(fx, fy);
            }
            x=fa[x];
            fx=top[x];
        }
        return dep[x] < dep[y] ? x:y;
    }
    
    1. 把从x到y的一条最短链上点的值改为z
    //把从x到y的最近链上点的值改为z;
    void update_chain(int x, int y, int z)
    {
        int fx=top[x], fy=top[y];
        while(fx!=fy)
        {
            if(dep[fx] < dep[fy])
            {
                swap(x, y);
                swap(fx, fy);
            }
            update(1, in[fx], in[x], z);
            //每往上跳一次,就修改以次经过路径上的值,因为DFS序中id[fx] < id[x],所以是区间[id[fx],id[x]];
        }
        if(in[x] > id[y]) 
            swap(x, y);
        update(1, in[x], in[y], z);
    }
    
    1. 求从x到y的最近一条链点值的总和。
    int query_chain(int x, int y)
    {
        int ans=0, fx=top[x], fy=top[y];
        while(fx!=fy)
        {
            if(dep[fx] < dep[fy])
            {
                swap(x, y);
                swap(fx, fy);
            }
            ans+=query(1, in[fx], in[x]);
        }
        if(in[x] > in[y])
            swap(x, y);
        ans+=query(1, in[x], in[y]);
        return ans;
    }
    
    欢迎评论交流!
  • 相关阅读:
    Angularjs 中文版API v1.3.9 阅读
    jquery之ajax
    requirejs中 shim
    reqiurejs学习
    angularjs与require的集成摘抄
    安装go-admin
    多种GitHub加速方式
    git初始化仓库操作
    git cherry-pick
    gc问题定位
  • 原文地址:https://www.cnblogs.com/alking1001/p/11402131.html
Copyright © 2011-2022 走看看