树链剖分相关

OI-WIKI

重链剖分

一些性质

  • 树上每个节点都属于且仅属于一条重链
  • 对于节点数为 n n n 的树,从任意节点向上走到根节点,经过的轻边数量不会超过 log ⁡ n \log n logn

一些特别操作

1.在线求LCA
int LCA(int x,int y){
    while(top[x]!=top[y])
      if(dep[top[x]]>dep[top[y]]) x=fa[top[x]];
      else y=fa[top[y]];
    return dep[x]<dep[y]?x:y;
}
2.换根操作

换一个根就重新剖一次当然是不现实的

不妨就先以1号节点为根剖一下

树链修改值当然直接按照重链在线段树上改就好了

主要就是讨论以x为根的子树对于不同的根时的dfn序范围

那么设当前的根是root

①:x==root:范围当然就是全局

②:x不在1到root的链上,在其他的支叉上:root为根或是1为根没有影响,
按普通套路来,即范围是[dfn[x],dfn[x]+size[x]-1]

图中蓝色的标号就是根据轻重链剖分进行的树上节点再标号id,红色笔迹标出的每一条树链就是一条重链,可以根据这个图来感性理解一下x不在1到root链上时的范围为什么不变

③:x在1到root的链上:这就是要处理的重点了

上图中紫色圈出的节点即是当前root,绿色圈出的节点即是要查询的子树的根x,那么可以看出当前x在1到root的链上。思考现在x的子树,其实就是除去x往root方向的那个子树外,所有的节点

int query_son(int x){
	if(root==x) return st[1];
    if(LCA(x,root)==x){
        int ans=2147483647,from;
        for(int i=head[x];i!=-1;i=edge[i].nxt)
          if(LCA(edge[i].v,root)==edge[i].v){
		  	  from=edge[i].v;
			  break;
		  }
        if(tid[from]>1) ans=min(ans,query(1,1,n,1,tid[from]-1));
        if(tid[from]+size[from]<=n) ans=min(ans,query(1,1,n,tid[from]+size[from],n));
        return ans;
    }
    return query(1,1,n,tid[x],tid[x]+size[x]-1);
}
之前碰到的一种解题操作

在这里插入图片描述

长链剖分

博客

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值