树链剖分

本文详细阐述了树链剖分的概念、构造方法、维护策略,并通过具体实例介绍了其在解决路径查询问题中的应用。同时,文章指出树链剖分并非单一的数据结构,而是一种将树结构转化为链状结构的技术,旨在为使用其他高效数据结构提供便利。通过实例分析,读者能够清晰地了解如何利用树链剖分优化路径查询操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

还是太弱啊。。各种数据结构只听过名字却没有一点概念。。树链剖分也在这个范畴。。今天来进一步深化一下教育改革推进全民素质提高。

性质

忘了在哪里看到的一篇blog有一句话讲得非常好,树链剖分不是一种数据结构,它只是将二维的树hash到一条一维的链上,为运用各种其他数据结构创造条件。

构造方法(或者说标准 并不知道为什么,然而它就是这么剖的,按照每个节点的儿子个数,相对应地接在其父节点后或自己自成一条重链——这样貌似在平均情况下可以使分成的链条数最少,每条链上的点多——不然为什么不按照顺序...更简单..

维护方法 在一条链上不套个什么东西都太浪费了,那么当我们要更新一条路径时,因为在同一条重链上的点的重编号是连续的,我们可以很方便的更新,再联想我们平时暴力更新的做法——lca,那么我们就可以用这种思想将两个点不断调整上移直到两个点在一条重链内,那么更新的操作就完成了。

BZOJ1036:一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身

终于还是A掉了,发现了两个问题..

一个是读入修改的时候忘记把读入的点的编号改成在链中的编号了,这真的是非常。。还有一个就是在LCA往上走的时候在最后自作聪明的想去掉重复——然而结果就是最后那个点根本就不会算!

不管怎么说又多了一个版子——虽然这么长(然而貌似还可以了,毕竟手打并无参考...时间虽然不是非常优秀(比黄学长快啦啦啦

/**************************************************************
    Problem: 1036
    User: wyc184
    Language: C++
    Result: Accepted
    Time:2400 ms
    Memory:7300 kb
****************************************************************/
 
#define me AcrossTheSky 
#include <cstdio> 
#include <cmath> 
#include <ctime> 
#include <string> 
#include <cstring> 
#include <cstdlib> 
#include <iostream> 
#include <algorithm> 
 
#include <set> 
#include <map> 
#include <stack> 
#include <queue> 
#include <vector> 
#define lowbit(x) (x)&(-x) 
#define INF 1070000000 
#define FOR(i,a,b) for((i)=(a);(i)<=(b);(i)++) 
#define FORP(i,a,b) for(int i=(a);i<=(b);i++) 
#define FORM(i,a,b) for(int i=(a);i>=(b);i--) 
#define ls(a,b) (((a)+(b)) << 1) 
#define rs(a,b) (((a)+(b)) >> 1)
#define MAXN 60001
using namespace std; 
typedef long long ll; 
typedef unsigned long long ull; 
/*==================split line==================*/
struct Edge{
    int x,y;
}e[MAXN*2];
 
int q,xx,L,R;
int n,sume;
int fa[MAXN],size[MAXN],depth[MAXN],sonh[MAXN],ord[MAXN],top[MAXN];
int first[MAXN],next[MAXN];
int max(int a,int b){
    return a>b?a:b;
}
struct Interval_Tree{ //线段树最大值和和的维护 
    int _max[MAXN*2],_sum[MAXN*2],v[MAXN*2];
 
    void updata(int node,int l,int r){
        if (l==r) {
            v[node]=xx; _max[node]=xx; _sum[node]=xx; 
            return;
        }
        int mid=rs(l,r); int lc=ls(node,0),rc=lc+1;
        if (q<=mid) updata(lc,l,mid);
            else updata(rc,mid+1,r);
 
        _max[node]=max(_max[lc],_max[rc]);
        _sum[node]=_sum[lc]+_sum[rc];
    }
    int Max(int node,int l,int r){
        if (L<=l && r<=R) return _max[node];
 
        int mid=rs(l,r),lc=ls(node,0),rc=lc+1,m=-INF;
        if (L<=mid) m=max(m,Max(lc,l,mid));
        if (mid<R) m=max(m,Max(rc,mid+1,r));
        return m;
    }
    int Sum(int node,int l,int r){
        if (L<=l && r<=R) return _sum[node];
 
        int mid=rs(l,r),lc=ls(node,0),rc=lc+1,tot=0;
        if (L<=mid) tot+=Sum(lc,l,mid);
        if (R>mid) tot+=Sum(rc,mid+1,r);
        return tot;
    }
    void check(){
        FORP(i,1,n*2) printf("%d ",_max[i]);
        cout << endl;
    }
}tree;
void addedge(int x,int y){ //邻接表的添加 
    e[sume].x=x,e[sume].y=y;
    next[sume]=first[x];
    first[x]=sume;
}
int build_tree(int node,int dep){//树上结点的深度、儿子总数、父亲以及重儿子的维护 
    depth[node]=dep;
    int Max=0,u=0;
    for (int i=first[node];i!=-1;i=next[i]){
        if (e[i].y!=fa[node]){
            fa[e[i].y]=node;  int counter=build_tree(e[i].y,dep+1);
            if (counter>Max) { Max=counter; u=e[i].y; }
            size[node]+=counter;
        }
    }
    sonh[node]=u;
    return size[node]+1;
}
int p=1;
void mark(int node,int topn){//重新编号 
    ord[node]=p;top[node]=topn;
     
    if (sonh[node]!=0) {
        p++; mark(sonh[node],topn);
    }
    for (int i=first[node];i!=-1;i=next[i])
    if (e[i].y!=fa[node] && e[i].y!=sonh[node]){
        p++;
        mark(e[i].y,e[i].y);
    }
    return ;
}
int QSUM(int a,int b){ //求两个点之间的路径和 ——这些操作都是在重编号下完成的 
    int sum=0;
    while (top[a]!=top[b]){ //如果两个点不在一条重链上 
        if (depth[top[a]]<depth[top[b]]){ //比较两条重链的深度,将深的那条往上调 
            L=ord[b],R=ord[top[b]]; if (L>R) swap(L,R);
            sum+=tree.Sum(1,1,n); //线段树查询 
            b=fa[top[b]]; //将b更新为这条重链头的父亲 
        }
        else { 
            L=ord[a],R=ord[top[a]]; if (L>R) swap(L,R);
            sum+=tree.Sum(1,1,n);
            a=fa[top[a]];
        }
    }
        L=ord[a]; R=ord[b]; if(L>R) swap(L,R);
        sum+=tree.Sum(1,1,n);
    return sum;
}
 
int QMAX(int a,int b){
     int maxx=-INF;
     while (top[a]!=top[b]){
         if (depth[top[a]]<depth[top[b]]){
             L=ord[b],R=ord[top[b]]; if (L>R) swap(L,R);
             maxx=max(maxx,tree.Max(1,1,n));
             b=fa[top[b]];
         }
         else {
             L=ord[a],R=ord[top[a]]; if (L>R) swap(L,R);
             maxx=max(maxx,tree.Max(1,1,n));
             a=fa[top[a]];
         }
     }
        L=ord[a]; R=ord[b]; if(L>R) swap(L,R);
        maxx=max(maxx,tree.Max(1,1,n));
     return maxx;
}
int main(){ 
    cin >> n;
    for (int i=1;i<=n;i++) first[i]=-1,size[i]=0;
 
    FORP(i,1,n-1){
        int x,y; scanf("%d%d",&x,&y);
        sume++; addedge(x,y);
        sume++; addedge(y,x);
    }
 
    FORP(i,1,n) fa[i]=i;  
 
    size[1]=build_tree(1,1)-1;  mark(1,1);
     
    FORP(i,1,n){
        q=ord[i]; scanf("%d",&xx);  
        tree.updata(1,1,n);
    }
    int k;  cin >> k;
    FORP(i,1,k){
        char s[10]; scanf("%s",s); 
        if (s[0]=='C') { 
            scanf("%d%d",&q,&xx);
            q=ord[q];
            tree.updata(1,1,n);
            continue;
        }
        int x,y; scanf("%d%d",&x,&y);
        if (s[2]=='A')  printf("%d\n",QMAX(x,y));
            else printf("%d\n",QSUM(x,y));
    }
}


内容概要:本文以电商仓储物流机器人为案例,深度解析机器人开发全流程,涵盖ROS系统搭建、SLAM建图、路径规划、机械臂控制、多机调度等核心技术。首先介绍了分层模块化架构和核心硬件选型,如主控制器、激光雷达、深度相机、驱动底盘和协作机械臂。接着详细讲述了ROS系统开发的核心实战,包括环境感知与SLAM建图、自主导航与动态避障等技术,提供了代码示例和技术关键点。然后探讨了机械臂抓取任务开发,涉及视觉定位系统、运动规划与力控制。随后介绍了多机器人集群调度系统的任务分配模型和通信架构设计。还讨论了安全与可靠性保障措施,包括硬件级安全设计和软件容错机制。最后总结了实战问题与解决方案,以及性能优化成果,并推荐了四大核心代码库和仿真训练平台。 适合人群:对机器人开发感兴趣的研发人员,尤其是有一定编程基础并希望深入了解仓储机器人开发的技术人员。 使用场景及目标:①学习仓储机器人从系统集成到底层硬件部署的全流程;②掌握ROS系统开发的核心技术,如SLAM建图、路径规划、机械臂控制等;③理解多机器人集群调度和安全可靠性设计;④解决实际开发中的常见问题并优化系统性能。 阅读建议:本文内容详实,涵盖了从硬件选型到软件开发的各个方面,建议读者结合实际项目需求,逐步深入学习,并通过实践操作加深理解。同时,利用提供的开源项目和仿真训练平台进行实验和验证。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值