zoukankan      html  css  js  c++  java
  • 线段树优化建图学习笔记


    • 线线段树优化建图的作用

    问题

    NN 个节点, 执行 MM 次以下连边操作, 倩输出以 ss 为起点的单源最短路:

    1. aba ightarrow b
    2. a[l,r]a ightarrow [l, r]
    3. [l,r]b[l, r] ightarrow b

    a,b,l,r[1,106]a, b, l, r in [1, 10^6]

    若暴力建图, 时空复杂度高达 O(MN2)O(MN^2),
    于是 线段树优化建图 诞生了 .


    • 线线段树优化建图的实现

    建立两个 线段树, 分别为 入树出树, 暂且称两者为 In_tIn\_t, Out_tOut\_t .
    按照以下 55 条规则即可建出一个边数为 O(MlogN)O(MlogN) 的 “优秀” 图 .

    1. In_tIn\_t下往上 连边, Out_tOut\_t 则从 上往下 连边 .
    2. In_tIn\_tOut_tOut\_t 的叶子结点都对应 原节点, 所以两颗树的对应叶子结点之间连上 边权00无向边.
    3. 对于上述问题中的 11 操作, In_tIn\_taa 节点直接连向 Out_tOut\_t 中的 bb 节点 .
    4. 对于上述问题中的 22 操作, In_tIn\_taa 节点连向 Out_tOut\_tlogNlogN 个对应区间节点 .
    5. 对于上述问题中的 33 操作, In_tIn\_t 中的 logNlogN 个区间节点向 Out_tOut\_t 中的 bb 连边 .

    某些问题只需要实现 22,33 操作其中之一 ,

    • 若实现 22 操作, 建一个 出树 即可 .
    • 若实现 33 操作, 建一个 入树 即可 .

    题外话: 由于初学时不太清楚, 下方例题 22 无脑建了两颗树, 导致 22 个点始终超时 …


    • 线线段树优化建图的相关代码

    1. 建图

    这里给出 入树 建边, 出树 同理 (以下皆为动态开点) .

    void Build(int &k, int l, int r, int opt){
            k = ++ node_cnt;
            T[k].l = l, T[k].r = r;
            if(l == r){
                    Mp[opt][l] = k; // 原图中 l 对应线段树节点 k.
                    return ;
            }
            int mid = l+r >> 1;
            Build(T[k].lt, l, mid, opt), Build(T[k].rt, mid+1, r, opt);
            if(opt == 0) Add(T[k].lt, k), Add(T[k].rt, k); // In_t 建边.
            else Add(k, T[k].lt), Add(k, T[k].rt);	// Out_t 
    }
    
    2. 叶子节点连边

    注意是出树叶子到入树叶子连边 .

    void Connect_0(int k){
            int l = T[k].l, r = T[k].r;
            if(l == r){
                    Add(Mp[1][l], Mp[0][l]);
                    return ;
            }
            Connect_0(T[k].lt), Connect_0(T[k].rt);
    }
    
    3. 点 ightarrow区间 连边
    void Connect(int k, int u, int L, int R){
            int l = T[k].l, r = T[k].r;
            if(L <= l && r <= R){
                    if(l == r && u == Mp[1][l]) return ; // 判重边.
                    Add(u, k); return ;
            }
            int mid = l+r >> 1;
            if(L <= mid) Connect(T[k].lt, u, L, R);
            if(R > mid) Connect(T[k].rt, u, L, R);
    }
    
    4. 区间 ightarrow点 连边
    
    void Connect_2(int k, int L, int R, int v){
            int l = T[k].l, r = T[k].r;
            if(L <= l && r <= R){
                    if(l == r && v == Mp[0][l]) return ; //判重边.
                    Add(k, v); return ;
            }
            int mid = l+r >> 1;
            if(L <= mid) Connect_2(T[k].lt, u, L, R);
            if(R > mid) Connect_2(T[k].rt, u, L, R);
    }
    
    5. 最短路

    略.


    • 线线段树优化建图的应用

    1. NOI2019 弹跳
    2. SNOI2017炸弹
  • 相关阅读:
    SQLite数据库框架ORMLite与GreenDao的简单比较
    Spring Web MVC中的页面缓存支持 ——跟我学SpringMVC系列
    admin嵌套在spring mvc项目里,菜单栏点击新连接每次都会重置
    Spring MVC视图层:thymeleaf vs. JSP
    使用Spring标签库
    SpringMVC中Controller跳转到另一个Controller方法
    有趣iOS开展
    Java日期的格式String类型GMT,GST换算成日期Date种类
    javascript之Style物
    Tair LDB基于Prefixkey中期范围内查找性能优化项目总结
  • 原文地址:https://www.cnblogs.com/zbr162/p/11822551.html
Copyright © 2011-2022 走看看