首页 > 其他分享 >11.29闲话

11.29闲话

时间:2023-11-29 21:24:18浏览次数:27  
标签:11.29 int 闲话 top son dfn siz 节点

今天也是为了解LCA,然后学了树链剖分

这边写个讲解

树剖分为重链剖分和长链剖分

通常指的是重链剖分

重链剖分

对于任意一个位于树上的节点

重子节点 表示其子节点中子树最大的子结点。如果有多个子树最大的子结点,取其一。如果没有子节点,就无重子节点。

轻子节点 表示剩余的所有子结点

重边 表示这个结点到重子节点的边

轻边 表示这个结点到其他轻子节点的边为

重链 表示若干条首尾衔接的重边

把落单的结点也当作重链,那么整棵树就被剖分成若干条重链

借用一下OI-wiki的图片

实现

首先,要先预处理几个变量

每个结点的父节点,子树大小,深度,重子节点,所在重链的链顶,重边优先遍历时的DFS序,DFS序对应的结点编号

struct node{
    int fa/*父节点*/,dep/*深度*/,siz/*子树大小*/,son/*重子节点*/,top/*所在链的链顶*/;
    int dfn/*DFS序*/,rnk/*对应编号*/;
}T[MAXM];

预处理的方法就是两个DFS

  • 第一遍:记录父节点,深度,子树大小,重子节点
inline void Dfs1(int q){
    T[q].son=-1;
    T[q].siz=1;
    for(int j=head[q];j;j=NEXT[j]){
        if(j=T[q].fa) continue;
        T[j].dep=T[q].dep+1;
        T[j].fa=q;
        Dfs1(j);
        T[q].siz+=T[j].siz;
		if((T[q].son==-1)||(T[j].siz>T[T[q].son].siz)) T[q].son=j;
    }
}
  • 第二遍:记录所在链的链顶,DFS序,对应的rank
inline void Dfs2(int q,int v){
    T[q].top=v;
	T[q].dfn=++cnt;
	T[cnt].rnk=q;
	if(T[q].son==-1)
        return;
	Dfs2(T[q].son,v);
    for(int j=head[q];j;j=NEXT[j]){
        if((j!=T[q].fa)&&(j!=T[q].son))
            Dfs2(j,j);
    }
}

有啥用

首先,要用线段树维护

然后就可以

  1. 求树上两点路径权值和

  2. 维护子树上的信息(譬如将以\(x\)为根的子树的所有结点的权值增加\(v\))

  3. LCA (\(O(\log n)\)甚至常数小)


根本思想:对于两个不在同一重链内的节点,让他们不断地跳,使得他们处于同一重链上

求树上两点路径权值和

这个比较抽象

首先,怎么跳?

根据一个显然的结论:xT[x].top 中的节点在线段树上是连续的

结合深度dep

我们可以每次都让两个点的topdep大的向上跳

每次跳直接让x跳到T[x].top即可,然后线段树上更新

在最后两个点处于同一重边时因为结论

xT[x].top 中的节点在线段树上是连续的

所以可以直接进行线段树的查询

子树操作

因为一棵树的子树在线段树上是连续的

所以直接线段树修改即可

LCA

这个和求树上两点路径权值和差不多一样(

就是更简单一些

只要知道树上倍增求LCA的应该也都懂

甚至不用线段树

代码实现

int head[MAXM],NEXT[MAXM],TO[MAXM],cnt,tot,a[MAXM];
namespace Grape{
    inline void add(int u,int v){
        NEXT[++tot]=head[u];
        TO[tot]=v;
        head[u]=tot;
    }
}
namespace ST{
    #define mid (l+r)/2
    #define lC q<<1
    #define rC q<<1|1
    struct St{
        long long l,r,siz;
        long long lazy,dat;
    }t[0x66ccff];
    void build(int q,int l,int r){
        t[q].l=l;
        t[q].r=r;
        t[q].siz=r-l+1;
        if(l==r){
            t[q].dat=a[l];
            return;
        }
        build(lC,l,mid);
        build(rC,mid+1,r);
        t[q].dat=t[lC].dat+t[rC].dat;
    }
    void lazy(int q){
        t[lC].lazy+=t[q].lazy;
        t[lC].dat+=(t[lC].r-t[lC].l+1)*t[q].lazy;
        t[rC].lazy+=t[q].lazy;
        t[rC].dat+=(t[rC].r-t[rC].l+1)*t[q].lazy;
        t[q].lazy=0;
    }
    void change(int q,int l,int r,int v){
        if(t[q].l>r||t[q].r<l) return;
        if(t[q].l>=l && t[q].r<=r){
            t[q].lazy+=v;
            t[q].dat+=(t[q].r-t[q].l+1)*v;
            return;
        }
        if(t[q].lazy>0)
            lazy(q);
        change(lC,l,r,v);
        change(rC,l,r,v);
        t[q].dat=t[lC].dat+t[rC].dat;
    }
    long long asksum(int q,int l,int r){
        if(t[q].l>r || t[q].r<l) 
            return 0;
        if(t[q].l>=l && t[q].r<=r) 
            return t[q].dat;
        if(t[q].lazy>0) 
            lazy(q);
        return asksum(lC,l,r)+asksum(rC,l,r); 
    }
}
namespace killTree{
    struct node{
        int fa,dep,siz,son,top;
        int dfn,rnk;
    }T[MAXM];
    inline void Dfs1(int q){
        T[q].son=-1;
        T[q].siz=1;
        for(int j=head[q];j;j=NEXT[j]){
            if(j=T[q].fa) continue;
            T[j].dep=T[q].dep+1;
            T[j].fa=q;
            Dfs1(j);
            T[q].siz+=T[j].siz;
            if((T[q].son==-1)||(T[j].siz>T[T[q].son].siz)) T[q].son=j;
        }
    }
    inline void Dfs2(int q,int v){
        T[q].top=v;
        T[q].dfn=++cnt;
        T[cnt].rnk=q;
        if(T[q].son==-1)
            return;
        Dfs2(T[q].son,v);
        for(int j=head[q];j;j=NEXT[j]){
            if((j!=T[q].fa)&&(j!=T[q].son))
                Dfs2(j,j);
        }
    }
    inline void TreeAdd(int x,int y,int val){
        while(T[x].top!=T[y].top){
            if(T[T[x].top].dep<T[T[y].top].dep) 
                std::swap(x,y);
            ST::change(1,T[T[x].top].dfn,T[x].dfn,val);
            x=T[T[x].top].fa;
        }
        if(T[x].dep>T[y].dep) 
            std::swap(x,y);
        ST::change(1,T[x].dfn,T[y].dfn,val);
    }
    inline int TreeSum(int x,int y){
        int ans=0;
        while(T[x].top!=T[y].top){
            if(T[T[x].top].dep<T[T[y].top].dep) std::swap(x,y);
            ans=ans+ST::asksum(1,T[T[x].top].dfn,T[x].dfn);
            x=T[T[x].top].fa;
        }
        if(T[x].dep>T[y].dep) std::swap(x,y);
        return ans+ST::asksum(1,T[x].dfn,T[y].dfn);
    }
    inline void AddTree(int x,int y,int z){
        ST::change(1,T[x].dfn,T[x].dfn+T[x].siz-1,z);
    }
    inline int AskTree(){
        ST::asksum(1,T[x].dfn,T[x].dfn+T[x].siz-1);
    }
}

标签:11.29,int,闲话,top,son,dfn,siz,节点
From: https://www.cnblogs.com/LuoTianYi66ccff/p/17865883.html

相关文章

  • 每日总结11.29
    百度机器翻译SDK实验完成百度翻译GUI相关功能代码并测试调用,实现中文翻译成英文,英文翻译成中文。示例代码:packagebaidu.com;importokhttp3.*;importorg.json.JSONObject;importjava.io.*;classSample{publicstaticfinalStringAPI_KEY="";publics......
  • 2023.11.29 日记 Take it easy
    很不想把文化课写到日记里。但今天有点烦了。考试考的内容是要通过刷题得知的,并非学习。我已经在别的平台抱怨过很多次当今教育现状了,无济于事是肯定的,反而会打消学习的积极性。由于训练原因欠了很多课,再加上两个学校的进度不同、考试时间不同,我的学习成果实在像是被虫蛀了一样......
  • 23.11.29(代码大全2读书笔记)
    *第一部分打好基础 第一章欢迎进入软件构建的世界 >软件构建的定义:包括编码与调试、单元测试、规划构建、集成等,没有给出一个明确的定义。>软件构建的重要性:软件构建是编写大型项目最重要的、不可或缺的部分。 第二章用隐喻来更充分地理解软件开发 > 对软件开......
  • 11.29-task5-代码风格
    代码风格代码风格介绍修饰代码的前提是代码没有bug。。。两幅图中的代码对比,显然后一幅图的代码更加简洁,易懂。也方便之后很长时间后的再理解。缩进tab==4个空格当函数有多参数时换行当一个语句的字符数过长,要换行运算符对齐导入规范导入时要遵循同级文......
  • 聪明办法学python-11.27——11.29笔记打卡
    一、python中条件语句的应用总体代码结构为:ifTrue:dosomethingelse:doother简单描述为“True”为条件,当条件为真的时候,执行“dosomething”,否则就执行“doother”。例如:任务:实现一个函数,返......
  • 11.28闲话
    今天突然想起来几句歌词便是我掏空予你一半心房也借你一半替我浅吟低唱纵然纸片凉薄爱轻狂虚妄你歌声里亦浸着我的痴放越想越难受所以...推歌纸片人【ilem投稿九周年】这是图片V4:佬啊,佬啊怎么是纸片儿啊调啊,调啊调的我心动啊佬啊,佬啊怎么是纸片儿呐调啊,......
  • 2023-11-28 闲话 无人之境
    http://www.stat.ucla.edu/~sczhu/research_blog.html昨天只读了文章千古事,得失寸心知的一篇,非常非常大收获。感觉比以前水的东西有意义多了。以后考虑多上各种大学网站上搜教授主页,看paper或者article都是不错的选择是吧。......
  • 2023-11-17 闲话
    偶然看到这首词,于是想锐评一下:辛苦最怜天上月,一昔如环,昔昔都成玦。若似月轮终皎洁,不辞冰雪为卿热。无那尘缘容易绝,燕子依然,软踏帘钩说。唱罢秋坟愁未歇,春丛认取双栖蝶。Fuckingmasterpiece.昨天一个人发了个空间说要去CitadelSecurities写代码了。结果评论区炸了,大概内......
  • 闲话111.6
    好好好后天就要noip了......
  • 闲话11.11
    今天打了一场模拟赛,又垫底了......