前言

题目链接

题意

有 \(n\) 个点,\(q\) 次连边,以及起点 \(s\) 。连边具体分三种:

  1. \(1\) \(v\) \(u\) \(w\) 从 \(v\) 到 \(u\) 连一条边。
  2. \(2\) \(v\) \(l\) \(r\) \(w\) 从 \(v\) 向 \(l\) 到 \(r\) 所有点连一条边。
  3. \(3\) \(v\) \(l\) \(r\) \(w\) 从 \(l\) 到 \(r\) 所有点向 \(v\) 连一条边。

求所有点的最短路。

思路

以前做过一道比较类似的题:T'ill It's Over 都是线段树优化连边。

建立两棵线段树记为 \(A\) , \(B\) ,线段树 \(A\) 的所有结点向上连结父节点,线段树 \(B\) 的所有节点向下连结自己的子节点。

那么操作就可以看成 \(A\) 树对应区间连向 \(B\) 树对应区间,就转换为普通的线段树区间查询了。

现在需要考虑如何将 \(B\) 树的状态转换到 \(A\) 树上。

只需要将 \(B\) 树的结点连向 \(A\) 的对应结点就好了。

由于状态最后都会回归到 \(A\) 树中,所以最后查询 \(A\) 树中叶子结点区间为 \([i,i](i\in [1,n])\) 的点的最短路径,即为答案。

算法总时间复杂度为 \(O(n\log n*log((n+q)\log n))\) ,大概就是 \(O(n\log^2n)\) 级别的。

Code

#include <queue>
#include <cstdio>
#include <cstring>
using namespace std;
namespace Quick_Function {
template <typename Temp> void Read(Temp &x) {
x = 0; char ch = getchar(); bool op = 0;
while(ch < '0' || ch > '9') { if(ch == '-') op = 1; ch = getchar(); }
while(ch >= '0' && ch <= '9') { x = (x << 1) + (x << 3) + (ch ^ 48); ch = getchar(); }
if(op) x = -x;
}
template <typename T, typename... Args> void Read(T &t, Args &... args) { Read(t); Read(args...); }
template <typename Temp> Temp Max(Temp x, Temp y) { return x > y ? x : y; }
template <typename Temp> Temp Min(Temp x, Temp y) { return x < y ? x : y; }
template <typename Temp> Temp Abs(Temp x) { return x < 0 ? (-x) : x; }
template <typename Temp> void Swap(Temp &x, Temp &y) { x ^= y ^= x ^= y; }
}
using namespace Quick_Function;
#define INF 1e17
#define int long long
const int MAXN = 5e5 + 5;
const int MAXM = 5e6 + 5;
struct Edge { int To, Dist, Next; };
int head[MAXN], edgetot = 1;
Edge edge[MAXM];
void Addedge(int u, int v, int w) { edge[++edgetot].Next = head[u], edge[edgetot].To = v, edge[edgetot].Dist = w, head[u] = edgetot; }
struct Node {
int id, dis;
Node() {}
Node(int I, int D) { id = I, dis = D; }
friend bool operator < (Node x, Node y) { return x.dis > y.dis; }
};
priority_queue<Node> que;
int dis[MAXN];
bool vis[MAXN];
int n, q, s, p;
struct Segment_Node {
int l, r, id;
#define LS(x) (x << 1)
#define RS(x) (x << 1 | 1)
};
struct Segment_Tree {
Segment_Node t[MAXN << 2][2];//0为A线段树,1为B线段树
int tot;
void Build(int pos, int l, int r, int flag) {//初始化建树
t[pos][flag].l = l, t[pos][flag].r = r, t[pos][flag].id = ++tot;
if(l == r) {
if(l == s && !flag) p = t[pos][flag].id;
if(flag) Addedge(t[pos][1].id, t[pos][0].id, 0);//这里忘写调了半个小时QAQ
return;
}
int mid = (l + r) >> 1;
Build(LS(pos), l, mid, flag); Build(RS(pos), mid + 1, r, flag);
if(!flag) {
Addedge(t[LS(pos)][flag].id, t[pos][flag].id, 0);
Addedge(t[RS(pos)][flag].id, t[pos][flag].id, 0);
}
else {
Addedge(t[pos][flag].id, t[LS(pos)][flag].id, 0);
Addedge(t[pos][flag].id, t[RS(pos)][flag].id, 0);
Addedge(t[pos][1].id, t[pos][0].id, 0);
}
}
int Query(int pos, int x, int flag) {//查询区间为[x,x]的叶子结点
if(t[pos][flag].l == t[pos][flag].r) return t[pos][flag].id;
if(x <= t[LS(pos)][flag].r) return Query(LS(pos), x, flag);
else return Query(RS(pos), x, flag);
}
void Update1(int pos, int l, int r, int x, int w) {//一连多
if(l <= t[pos][1].l && t[pos][1].r <= r) {
Addedge(Query(1, x, 0), t[pos][1].id, w);
return;
}
if(l <= t[LS(pos)][1].r) Update1(LS(pos), l, r, x, w);
if(r >= t[RS(pos)][1].l) Update1(RS(pos), l, r, x, w);
}
void Update2(int pos, int l, int r, int x, int w) {//多连一
if(l <= t[pos][0].l && t[pos][0].r <= r) {
Addedge(t[pos][0].id, Query(1, x, 1), w);
return;
}
if(l <= t[LS(pos)][0].r) Update2(LS(pos), l, r, x, w);
if(r >= t[RS(pos)][0].l) Update2(RS(pos), l, r, x, w);
}
};
Segment_Tree tree;
void Dijkstra() {//最短路
for(int i = 1; i <= tree.tot; i++) dis[i] = INF;
que.push(Node(p, 0)); dis[p] = 0;
while(!que.empty()) {
int u = que.top().id; que.pop();
if(vis[u]) continue;
vis[u] = 1;
for(int i = head[u]; i; i = edge[i].Next) {
int v = edge[i].To;
if(dis[v] > dis[u] + edge[i].Dist) {
dis[v] = dis[u] + edge[i].Dist;
que.push(Node(v, dis[v]));
}
}
}
}
signed main() {
Read(n, q, s);
tree.Build(1, 1, n, 0); tree.Build(1, 1, n, 1);
for(int i = 1, opt, u, v, l, r, w; i <= q; i++) {
Read(opt, u);
if(opt == 1) {
Read(v, w);
tree.Update1(1, v, v, u, w);
}
else if(opt == 2) {
Read(l, r, w);
tree.Update1(1, l, r, u, w);
}
else {
Read(l, r, w);
tree.Update2(1, l, r, u, w);
}
}
Dijkstra();
for(int i = 1; i <= n; i++) printf("%lld ", dis[tree.Query(1, i, 0)] == INF? -1 : dis[tree.Query(1, i, 0)]);
return 0;
}

[题解] CF786B Legacy的更多相关文章

  1. CF786B Legacy(线段树优化建边)

    模板题CF786B Legacy 先说算法 如果需要有n个点需要建图 给m个需要建边的信息,从单点(或区间内所有点)向一区间所有点连边 如果暴力建图复杂度\(mn^2\) 以单点连向区间为例,在n个点 ...

  2. CF786B Legacy && 线段树优化连边

    线段树优化连边 要求点 \(x\) 向区间 \([L, R]\) 连边, 一次的复杂度上限为 \(O(n)\) 然后弄成线段树的结构 先父子连边边权为 \(0\) 这样连边就只需要连父亲就可以等效于连 ...

  3. 题解 CF786B 【Legacy】

    本题要求我们支持三种操作: ① 点向点连边. ② 点向区间连边. ③ 区间向点连边. 然后跑最短路得出答案. 考虑使用线段树优化建图. 建两颗线段树,入树和出树,每个节点为一段区间的原节点集合.入树内 ...

  4. CF786B Legacy 线段树优化建图

    问题描述 CF786B LG-CF786B 题解 线段树优化建图 线段树的一个区间结点代表 \([l,r]\) 区间点. 然后建立区间点的时候就在线段树上建边,有效减少点的个数,从而提高时空效率. 优 ...

  5. 线段树优化建图 || CF786B Legacy

    题面:786B - Legacy 代码: #include<cstdio> #include<cstring> #include<iostream> #includ ...

  6. CF786B Legacy 线段树优化建图 + spfa

    CodeForces 786B Rick和他的同事们做出了一种新的带放射性的婴儿食品(???根据图片和原文的确如此...),与此同时很多坏人正追赶着他们.因此Rick想在坏人们捉到他之前把他的遗产留给 ...

  7. CF786B Legacy(线段树优化建图)

    嘟嘟嘟 省选Day1T2不仅考了字符串,还考了线段树优化建图.当时不会,现在赶快学一下. 线段树能优化的图就是像这道题一样,一个点像一个区间的点连边,或一个区间像一个点连边.一个个连就是\(O(n ^ ...

  8. CF786B Legacy

    思路 线段树优化建图 基本思想就是要把一个区间连边拆成log个节点连边, 然后一颗入线段树,一颗出线段树,出线段树都由子节点向父节点连边(可以从子区间出发),入线段树从父节点向子节点连边(可以到达子区 ...

  9. 【CF786B】Legacy

    题目大意:初始给定 N 个点,支持三种操作:两点之间连边:一个点与一个连续区间编号的点之间连边:一个连续区间内的点和一个点连边,求执行 N 次操作之后的单源最短路. 题解:学会了线段树优化建图. 发现 ...

随机推荐

  1. springboot系列四:springboot整合mybatis jsp

    一.用IDEA 创建maven项目 项目目录结构 1.添加pom jar依赖 <?xml version="1.0" encoding="UTF-8"?& ...

  2. GUI编程学习笔记——day01

    GUI编程 前言:告诉大家应该怎么学? 这是什么? 它怎么玩? 该如何在我们平时运用? 组件 窗口 弹窗 面板 文本框 列表框 按钮 图片 监听事件 鼠标 键盘事件 破解工具 一.是什么 GUI是图形 ...

  3. Java应用性能瓶颈分析思路

    1 问题描述 因产品架构的复杂性,可能会导致性能问题的因素有很多.根据部署架构,大致的可以分为应用端瓶颈.数据库端瓶颈.环境瓶颈三大类.可以根据瓶颈的不同部位,选择相应的跟踪工具进行跟踪分析. 应用层 ...

  4. PAT (Basic Level) Practice (中文)1065 单身狗 (25 分) 凌宸1642

    PAT (Basic Level) Practice (中文)1065 单身狗 (25 分) 凌宸1642 题目描述: "单身狗"是中文对于单身人士的一种爱称.本题请你从上万人的大 ...

  5. ss 命令简介

    1. 简介 ss 使用 netlink 与内核 tcp_diag 模块通信获取 socket 信息,用法和输出结果类似于 netstat 命令 语法格式如下 ss [options] [ FILTER ...

  6. (原创)高DPI适配经验系列:(二)按DPI范围适配

    一.前言 一个软件,往往会用到位图资源,比如图标.图片.水晶按钮等. 在使用了位图资源后,就不能对任意DPI都进行适配,因为这样适配的代价太大了. 像Win10的缩放比例可以由100%-500%,如果 ...

  7. 基于scrapy框架的爬虫基本步骤

    本文以爬取网站 代码的边城 为例 1.安装scrapy框架 详细教程可以查看本站文章 点击跳转 2.新建scrapy项目 生成一个爬虫文件.在指定的目录打开cmd.exe文件,输入代码 scrapy ...

  8. 王炸!!IDEA 2021.1 推出语音、视频功能,边写代码边聊天,我真的服了…

    IDEA 2020.3 刚没用多久,2021.1 又陆续给我推送更新了: 启动就提醒更新,麻烦,那不如更新下,体验下新版本. 如上图所示,2021.1 更新了 9 个新特性,下面栈长会一一体验给大家介 ...

  9. SHA256sum系列命令检测文件完整性

    1 sha256sum sha256sum是一个检测文件完整性的命令,一般下载的文件都会附带一个哈希值,使用sha256sum计算下载文件的哈希值再与目标哈希值比较即可确定文件是否完整,类似的命令还有 ...

  10. 1149 Dangerous Goods Packaging

    When shipping goods with containers, we have to be careful not to pack some incompatible goods into ...