【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].rc
struct 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 -> out
if (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;
}
【CF786B】Legacy的更多相关文章
- 【翻译】Sencha Touch2.4 The Layout System 布局
[翻译]The Layout System 布局 In Sencha Touch there are two basic building blocks: componentsand containe ...
- 【转】在RedHat上搭建自己Email服务器
原文:http://6839976.blog.51cto.com/6829976/1323482 by LN__@linux 目前邮件服务器中,想要拥有自己的邮件服务器,单单使用senmail,pos ...
- 在前端页面中使用@font-face来显示web自定义字体【转】
本文转自W3CPLUS 的<CSS @font-face> @font-face是CSS3中的一个模块,他主要是把自己定义的Web字体嵌入到你的网页中,随着@font-face模块的出现, ...
- 【翻译】Flume 1.8.0 User Guide(用户指南) Processors
翻译自官网flume1.8用户指南,原文地址:Flume 1.8.0 User Guide 篇幅限制,分为以下5篇: [翻译]Flume 1.8.0 User Guide(用户指南) [翻译]Flum ...
- 【翻译】Flume 1.8.0 User Guide(用户指南) source
翻译自官网flume1.8用户指南,原文地址:Flume 1.8.0 User Guide 篇幅限制,分为以下5篇: [翻译]Flume 1.8.0 User Guide(用户指南) [翻译]Flum ...
- 【教程】在UEFI启动方式下,通过GRUB2引导,直接从硬盘ISO文件安装Windows10和Ubuntu双系统
本文为作者原创,允许转载,但必须注明原文地址: https://www.cnblogs.com/byronxie/p/9949789.html 动机 最近在自学MIT6.828 Operating S ...
- 【转】PEP8 规范
[转]PEP8 规范 Python PEP8 编码规范中文版 原文链接:http://legacy.python.org/dev/peps/pep-0008/ item detail PEP 8 ...
- 【转】CSS3属性 @font-face 整理
原文: http://www.w3cplus.com/content/css3-font-face 出自: w3cplus.com 一.语法规则 @font-face { font-family: & ...
- 【Java】-NO.20.Exam.1.Java.1.001- 【1z0-807】- OCEA
1.0.0 Summary Tittle:[Java]-NO.20.Exam.1.Java.1.001-[1z0-807] Style:EBook Series:Java Since:2017-10- ...
随机推荐
- 浅谈 OpenResty,基于opebresty+redis进行实时线上限流
一.前言 我们都知道Nginx有很多的特性和好处,但是在Nginx上开发成了一个难题,Nginx模块需要用C开发,而且必须符合一系列复杂的规则,最重要的用C开发模块必须要熟悉Nginx的源代码,使得开 ...
- Stream系列(十)Count方法使用
计数器 视频讲解: https://www.bilibili.com/video/av77905733/ EmployeeTestCase.java package com.example.demo; ...
- Mac 操作小技巧
系统版本 MacOs Mojava # 快捷键篇: 1. 打开终端:command+空格,输入terminal:在终端页面,新建终端command + T 2. 打开文件夹:command + T 3 ...
- serverlet声明周期
servlet生命周期 被创建:默认情况下,当servlet第一次被访问时,由服务器创建该对象,调用init()初始化方法,一个servlet只会被创建一次. 可以配置servlet让其他服务器启动时 ...
- 一文搞懂 Java 中的枚举,写得非常好!
知识点 概念 enum的全称为 enumeration, 是 JDK 1.5 中引入的新特性. 在Java中,被 enum关键字修饰的类型就是枚举类型.形式如下: enum Color { RED, ...
- 基于licode搭建webrtc服务器
0. 前言 licode官网文档安装教程十分简单, 但是实际搭建过程是很艰辛的. 官方文档没有提示说会遇到什么样的问题, 实际过程中可能遇到各种各样的问题, 在解决的时候费时费力, 我就总结一下自己在 ...
- Jmeter之Dummy Sampler
Dummy Sampler(Dummy取样器) Dummy Sampler就像是一个模拟器,需要自己填入请求和响应的信息.(原理类似mock服务) 在没有服务的情况下,测试人员依据Dummy Samp ...
- X86逆向2:提取按钮通杀特征码
本章我们将学习特征码的提取与定位,特征码是软件中一段固定的具有标志性的代码片段,特征码的用途非常广泛,最常见的就是杀毒软件的查杀了,查杀就是根据特征码定位技术实现的,再比如木马的免杀也是修改了特征码的 ...
- webpack编写一个plugin插件
插件向第三方开发者提供了 webpack 引擎中完整的能力.使用阶段式的构建回调,开发者可以引入它们自己的行为到 webpack 构建流程中.创建插件比创建 loader 更加高级,因为你将需要理解一 ...
- Scala学习十二——高阶函数
一.本章要点 在Scala中函数是”头等公民“(可以作为参数,返回值,赋值给其他); 可以创建匿名函数,通常还会交给其他函数; 函数参数可以给出需要稍后执行的行为; 许多集合方法都接受函数参数,将函数 ...