线段树优化建图

两道相对模板的例题,都是线段树优化建图之后跑最短路。

分几种情况:

  • 点向点连边
  • 点向区间连边
  • 区间向点连边
  • 区间向区间连边

显然,如果直接建图,每次能建立 (n^2) 数量级的边,总边数大概是 (O(mn^2))(因为重边会多次计算),空间复杂度不允许。

对于区间问题,我们有神器:线段树。

既然直接连边太麻烦,那么就可以用线段树上的一个节点代表图上的一个区间的点。

不过,在同一棵线段树上维护这些点会很混乱。所以我们考虑用两棵线段树维护分别这些点的出边和入边,称为 出树、入树

对于出树,每个区间的两个子区间向当前区间连边权为 0 的边(以下简称 0 边);

对于入树,每个区间向两个子区间连 0 边。

这个是显然的,在小区间和大区间之间穿梭不需要代价。

虽然建两棵线段树,但事实上,入树上的节点 dis 值更改后应该都可以更新出树上的点进一步更新其他节点的 dis 值,所以应该有入树向出树连的 0 边。

而对于叶子节点,还应该有出树向入树连的 0 边(自己到自己的 dis 值为 0)。

处理好细节,代码就是这样:

const int inf=2e6+7;
int n,m,s;
struct edge{
    int to;ll val;
    edge(int to,ll val):to(to),val(val){}
};
vectore[inf];
void ins(int x,int y,ll z)
{//vector 存图
    e[x].push_back(edge(y,z));
}
struct Seg_Tree{
    int le,ri;
    int id;
}O[inf],I[inf];//out 出树,in 入树
int leafO[inf],leafI[inf],sum;//存放叶子节点
void build(int i,int l,int r)
{
    O[i].le=I[i].le=l,O[i].ri=I[i].ri=r;
    O[i].id=++sum,I[i].id=++sum;
    ins(I[i].id,O[i].id,0);//入树向出树建 0 边
    if(l==r)
    {//叶子节点
        leafO[l]=O[i].id;
        leafI[l]=I[i].id;
        ins(O[i].id,I[i].id,0);
        return;
    }
    int lc=i<>1;
    build(lc,l,mid);
    build(rc,mid+1,r);
    //出树子区间向当前区间连 0 边
    ins(O[lc].id,O[i].id,0);
    ins(O[rc].id,O[i].id,0);
    //入树当前区间向子区间连 0 边
    ins(I[i].id,I[lc].id,0);
    ins(I[i].id,I[rc].id,0);
}

作为最简单的一种情况,直接在出树和入树的两个叶子节点之间建边即可。

if(op==1)
{
    int u=re(),v=re(),w=re();
    ins(leafO[u],leafI[v],w+0ll);
}

在入树上找到对应的区间,然后建边。

void askI(int x,int i,int l,int r,ll k)
{
    if(l>1;
    if(l

和 2. 差不多,只是换成在出树上找对应区间。

void askO(int i,int l,int r,int x,ll k)
{
    if(l>1;
    if(l

对于这种情况,并不是对应区间向对应区间全部连边,而是找一个中介点,出树对应区间向中介点连边,中介点向入树对应区间连边。

void askO(int i,int l,int r,int x)
{
    if(l>1;
    if(l>1;
    if(l

最短路

这种题最恶心的地方就是建图,建完图之后跑裸的 dijkstra 就可以了。

当然,最终的答案应该是入树的叶节点的 dis 值。

AC Code:

CF786B

const int inf=2e6+7;
int n,m,s;
struct edge{
    int to;ll val;
    edge(int to,ll val):to(to),val(val){}
};
vectore[inf];
void ins(int x,int y,ll z)
{
    e[x].push_back(edge(y,z));
}
struct Seg_Tree{
    int le,ri;
    int id;
}O[inf],I[inf];
int leafO[inf],leafI[inf],sum;
void build(int i,int l,int r)
{
    O[i].le=I[i].le=l,O[i].ri=I[i].ri=r;
    O[i].id=++sum,I[i].id=++sum;
    ins(I[i].id,O[i].id,0);
    if(l==r)
    {
        leafO[l]=O[i].id;
        leafI[l]=I[i].id;
        ins(O[i].id,I[i].id,0);
        return;
    }
    int lc=i<>1;
    build(lc,l,mid);
    build(rc,mid+1,r);
    ins(O[lc].id,O[i].id,0);
    ins(O[rc].id,O[i].id,0);
    ins(I[i].id,I[lc].id,0);
    ins(I[i].id,I[rc].id,0);
}
void askO(int i,int l,int r,int x,ll k)
{
    if(l>1;
    if(l>1;
    if(lb.val;
    }
};
priority_queueh;
ll dis[inf];
bool vis[inf];
signed main()
{
    n=re();m=re();s=re();
    build(1,1,n);
    for(int i=1;idis[now]+e[now][i].val)
            {
                dis[p]=dis[now]+e[now][i].val;
                h.push(node(p,dis[p]));
            }
        }
    }
    for(int i=1;i

P6348

const int inf=1e7+7;
int n,m,s;
struct edge{
    int to,val;
    edge(int to,int val):to(to),val(val){}
};
vectore[inf];
void ins(int x,int y,int z)
{
    e[x].push_back(edge(y,z));
}
struct Seg_Tree{
    int le,ri;
    int id;
}O[inf],I[inf];
int leafO[inf],leafI[inf],cnt;
void build(int i,int l,int r)
{
    O[i].le=I[i].le=l;O[i].ri=I[i].ri=r;
    O[i].id=++cnt;I[i].id=++cnt;
    ins(I[i].id,O[i].id,0);
    if(l==r)
    {
        leafO[l]=O[i].id;
        leafI[l]=I[i].id;
        ins(O[i].id,I[i].id,0);
        return;
    }
    int lc=i<>1;
    build(i<>1;
    if(l>1;
    if(lb.val;
    }
};
priority_queueh;
int dis[inf];
bool vis[inf];
int main()
{
    n=re();m=re();s=re();
    build(1,1,n);
    for(int i=1;idis[now]+e[now][i].val)
            {
                dis[p]=dis[now]+e[now][i].val;
                h.push(node(p,dis[p]));
            }
        }
    }
    for(int i=1;i>1),putchar('\n');
    return 0;
}

当然,线段树优化建图不止用于最短路,多数图论问题都可以利用线段树优化建图。

Original: https://www.cnblogs.com/Zvelig1205/p/16670596.html
Author: Zvelig1205
Title: 线段树优化建图

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/605295/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 最短编辑距离

    给定 n 个长度不超过 10 的字符串以及 m 次询问,每次询问给出一个字符串和一个操作次数上限。 对于每次询问,请你求出给定的 n 个字符串中有多少个字符串可以在上限操作次数内经…

    数据结构和算法 2023年6月7日
    079
  • 大前端算法篇之二叉树遍历

    二叉树遍历: 前序遍历:先输出当前节点;然后遍历左子树,如果左子树不为空,递归前序遍历;接着遍历右子树,如果右子树不为空,递归前序遍历 中序遍历:先遍历当前节点左子树,如果不为空,…

    数据结构和算法 2023年6月7日
    065
  • 07 sql函数

    函数:切记函数和括号要紧密相连内置函数1.算术函数abs mod roundmax min avg sum count 这几个为聚集函数,特别在分组中常用 select abs(-…

    数据结构和算法 2023年6月8日
    081
  • 算法: 从上到下打印二叉树

    问题: 从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印。 解决 /** * Definition for a binary tree node. * publi…

    数据结构和算法 2023年6月12日
    069
  • MySQL InnoDB缓存

    1. 背景 对于各种用户数据、索引数据等各种数据都是需要持久化存储到磁盘,然后以”页”为单位进行读写。 相对于直接读写缓存,磁盘IO的成本相当高昂。 对于读…

    数据结构和算法 2023年6月8日
    073
  • golang初探

    最近两天对go语言做了一个初步的了解,记录一下。之前没有按照原创发表,所以重新发布一次。 第一个感受就是使用起来方便,从官网下载安装包,参考https://golang.googl…

    数据结构和算法 2023年6月16日
    062
  • 二叉树——结构查找相关问题

    判断t1树是否包含t2树的所有拓扑结构 1.1. 问题 给定彼此独立的两棵树头节点分别为 t1 和 t2,判断 t1 树是否包含 t2 树全部的拓扑结构。 1.2. 思路 题目这里…

    数据结构和算法 2023年6月10日
    073
  • 双向链表

    list简介 双向链表,可以从任何地方快速插入与删除 线性链表结构,数据由若干节点构成,每一个结点都包括一个信息块(实际存储的数据)、一个前驱指针和一个后驱指针。它无需分配指定的内…

    数据结构和算法 2023年6月13日
    077
  • 树形dp(背包)

    树形dp 样题: 没有上司的舞会 某大学有 (n) 个职员,编号为 (1\ldots n)。 他们之间有从属关系,也就是说他们的关系就像一棵以校长为根的树,父结点就是子结点的直接上…

    数据结构和算法 2023年6月8日
    058
  • 算法:回文子字符串的个数

    问题 给定一个字符串 s ,请计算这个字符串中有多少个回文子字符串。 具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。 解决 //1、遍历统计(双指…

    数据结构和算法 2023年6月12日
    073
  • 使用maven下载jar包

    在任意目录下创建一个文件夹,其下创建一个 pom.xml文件 pom.xml 不需要实际项目中那么复杂,示例如下

    数据结构和算法 2023年6月16日
    0104
  • 初等数论学习笔记 I:同余相关

    2021.12.6:重构文章,删去线性筛部分,修改部分表述。 2022.3.15:重构文章。 2022.3.24:新增威尔逊定理,素数在阶乘和组合数中的幂次,阶与原根,高次剩余和卢…

    数据结构和算法 2023年6月12日
    090
  • 杨卓凡小定理

    杨卓凡小定理系列 (k) 层整除分块时间复杂度:(O\left(n^{\frac{2^k-1}{2^k}}\right)) . 证明:考虑用数学归纳法,(k=1) 显然成立 . (…

    数据结构和算法 2023年6月7日
    082
  • Python <算法思想集结>之抽丝剥茧聊动态规划

    1. 概述 &#x52A8;&#x6001;&#x89C4;&#x5212;算法应用非常之广泛。 对于算法学习者而言,不跨过 &#x52A8…

    数据结构和算法 2023年6月7日
    082
  • AcWing 第14场周赛

    #include<cstdio> #include<cstring> #include<iostream> #include<ctime&…

    数据结构和算法 2023年6月7日
    086
  • django后台服务器优化

    背景留言板小程序的后台是采用djando进行开发的,数据库引擎是使用的mysql,由于原阿里云的服务器配置比较低,cpu只有1核,内存只有1G,在用户比较集中访问留言板小程序的时候…

    数据结构和算法 2023年6月16日
    066
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球