【CF786B】Legacy
题目大意:初始给定 N 个点,支持三种操作:两点之间连边;一个点与一个连续区间编号的点之间连边;一个连续区间内的点和一个点连边,求执行 N 次操作之后的单源最短路。
题解:学会了线段树优化建图。
发现若暴力进行连边,时间和空间都会被卡到 \(O(n^2)\),直接起飞。
发现连边的点的编号是连续的,结合线段树可以维护连续区间信息的思想,就产生了线段树优化建图的方法。
在初始的 N 个节点的基础上建立两棵线段树,分别表示入树和出树,其中入树的上的各个节点允许单个节点的连接;出树上的节点允许连接单个节点。对于入树中的每个节点来说,需要连一条边权为 0 的有向边到它的两个儿子,表示若有节点连向父节点,那么一定也连向了儿子节点;对于出树上的每个节点来说,需要连一条边权为 0 的有向边到它的父节点,表示若当前节点可以连向某个节点,那么其子节点也一定可以走到这个节点。
时空复杂度分析:空间为两棵线段树的空间减去一份叶子节点的大小,即:\(3 * n\),时间复杂度为 \(elog^2v\),其中 e 是边的条数,v 是节点的个数。
代码如下
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;struct edge {int to;LL w;edge(int x = -1, int y = -1) {to = x, w = y;}
};struct segtree {#define ls(o) tree[o].lc#define rs(o) tree[o].rcstruct node {int lc, rc;};vector<node> tree;int tot, rootin, rootout;segtree(int n, vector<vector<edge>> &adj) {tot = n;tree.resize(3 * n);buildin(rootin, 1, n, adj);buildout(rootout, 1, n, adj);}void buildin(int &o, int l, int r, vector<vector<edge>> &adj) {if (l == r) {o = l;return;}o = ++tot;int mid = l + r >> 1;buildin(ls(o), l, mid, adj);buildin(rs(o), mid + 1, r, adj);adj[o].emplace_back(ls(o), 0);adj[o].emplace_back(rs(o), 0);}void buildout(int &o, int l, int r, vector<vector<edge>> &adj) {if (l == r) {o = l;return;}o = ++tot;int mid = l + r >> 1;buildout(ls(o), l, mid, adj);buildout(rs(o), mid + 1, r, adj);adj[ls(o)].emplace_back(o, 0);adj[rs(o)].emplace_back(o, 0);}void link(int o, int l, int r, int x, int y, int u, int w, int opt, vector<vector<edge>> &adj) {// opt 2 -> in 3 -> outif (l == x && r == y) {opt == 2 ? adj[u].emplace_back(o, w) : adj[o].emplace_back(u, w);return;}int mid = l + r >> 1;if (y <= mid) {link(ls(o), l, mid, x, y, u, w, opt, adj);} else if (x > mid) {link(rs(o), mid + 1, r, x, y, u, w, opt, adj);} else {link(ls(o), l, mid, x, mid, u, w, opt, adj);link(rs(o), mid + 1, r, mid + 1, y, u, w, opt, adj);}}
};int main() {ios::sync_with_stdio(0);cin.tie(0), cout.tie(0);int n, m, s;cin >> n >> m >> s;vector<vector<edge>> adj(3 * n);segtree t(n, adj);while (m--) {int opt;cin >> opt;if (opt == 1) {int u, v, w;cin >> u >> v >> w;adj[u].emplace_back(v, w);} else {int u, l, r, w;cin >> u >> l >> r >> w;t.link(opt == 2 ? t.rootin : t.rootout, 1, n, l, r, u, w, opt, adj);}}vector<LL> d(3 * n, 1e18);vector<bool> expand(3 * n);priority_queue<pair<LL, int>> q;auto dijkstra = [&]() {d[s] = 0, q.push(make_pair(0, s));while (!q.empty()) {int u = q.top().second;q.pop();if (expand[u] == 1) {continue;}expand[u] = 1;for (auto e : adj[u]) {int v = e.to, w = e.w;if (d[v] > d[u] + w) {d[v] = d[u] + w;q.push(make_pair(-d[v], v));}}}};dijkstra();for (int i = 1; i <= n; i++) {if (d[i] == 1e18) {cout << "-1" << " ";} else {cout << d[i] << " ";}}return 0;
}
转载于:https://www.cnblogs.com/wzj-xhjbk/p/11528900.html
【CF786B】Legacy相关推荐
- Android启动过程深入解析【转】
转自:http://www.open-open.com/lib/view/open1403250347934.html 当按下Android设备电源键时究竟发生了什么? Android的启动过程是怎么 ...
- 【STM32】低功耗相关函数和类型
00. 目录 文章目录 00. 目录 01. 概述 02. 相关类型 03. 相关函数 04. 结构体封装 05. 预留 06. 附录 07. 声明 01. 概述 很多单片机都有低功耗模式,STM32 ...
- 【STM32】GPIO功能复用
00. 目录 文章目录 00. 目录 01. GPIO复用概述 02. 寄存器描述 03. 类型 04. 函数 05. 参考示例 06. 附录 07. 声明 01. GPIO复用概述 STM32F4 ...
- 【STM32】GPIO相关函数和类型
00. 目录 文章目录 00. 目录 01. GPIO固件库概述 02. GPIO相关类型 03. GPIO相关宏 04. GPIO相关函数 05. GPIO其它相关 06. 附录 07. 声明 01 ...
- 【Linux】一步一步学Linux——telinit命令(144)
00. 目录 文章目录 00. 目录 01. 命令概述 02. 命令格式 03. 常用选项 04. 参考示例 05. 附录 01. 命令概述 设置当前系统的运行等级 说明: This is a leg ...
- 【Maven】Maven POM配置详解
就像web项目的核心是web.xml一样,Maven项目的核心是pom.xml,POM(project object model,项目对象模型)定义了项目的基本信息,用于描述项目如何构建,如何声明依赖 ...
- 【Ogre-windows】环境配置
前言 由于工程原因, 学习一下Ogre面向对象图形渲染开源引擎, 慢慢爬坑吧.首先还是环境的配置问题哎. 其实最重要的是要预先编译三方库, 虽然官方说可以自动编译, 但是在自己电脑上还是出现了无法解析 ...
- [DIV/CSS] 【译】60个有用CSS代码片段
2019独角兽企业重金招聘Python工程师标准>>> 1.垂直对齐 如果你用CSS,则你会有困惑:我该怎么垂直对齐容器中的元素?现在,利用CSS3的Transform,可以很优雅的 ...
- win8服务器无法安装win7系统安装,win8怎么安装win7 win8改win7教程详解【图文】
继win7系统后,微软又推出了win8.win8.1以及win10系统,每个系统在原来的版本上都有了更改和创新.大家都知道,人是一种容易习惯的动物.很多人在使用了win7之后,更换到win8系统会很不 ...
最新文章
- 一套使用注入和Hook技术托管入口函数的方案
- python 浏览器显示本地文件夹_从浏览器中打开本地文件文件夹
- 余切表示matlab,matlab中 正弦余弦正切余切的画法 以及For while的用法
- flink的CEP调研与使用
- hive 多用户访问模注意问题
- 小C语言程序----词法分析程序输出单词
- Exchange 2013SP1和O365混合部署系列二
- HDU各种比赛题题解(一)
- 倾囊传授DELL主板BIOS设置
- LR之Java Vuser
- snownlp抛出错误_请教大家有关SnowNLP分词、词性标注、情感分析的问题
- Delphi FastReport组件下载,包含多个版本,自己选择
- 穷查理宝典_穷查理宝典
- 十大新兴编程语言_十大编程语言
- 关于#!/bin/bash
- linux 儒略日时间计算,儒略日(儒略日 在线计算器)
- mysql数据库的语句
- Creator新手引导 | 限制只能点击一个按钮 | 文字打字机效果
- PowerPoint 中缺少think-cell 加载项丨解决方案丨使用教程
- php字符串操作整理,PHP 字符串操作整理
热门文章
- C#——if 和 Switch 的区别,与在内存中的占有量
- 风水 第一节 环境感受简谈
- “炒房团”攻占元宇宙,有人2732万买入一块虚拟土地,林俊杰也花78万入手了
- 电商项目的介绍及其框架搭建
- USB Type-C学习点滴
- 为什么自己干了这么多活,最后功劳都是别人的?
- Map集合中两个重要的取值方法---keySet()和entrySet()
- cf - 922C - Cave Painting ( 思维 + 数学 )
- Java 实现双色球的彩票功能。规则:从33个红球中随机选择不重复的6个数,从16个蓝球中随机选择1个组成一注彩票。可以选择买多注。
- 硬盘分区表的数据结构