CF786B Legacy(线段树优化建图)
嘟嘟嘟
省选Day1T2不仅考了字符串,还考了线段树优化建图。当时不会,现在赶快学一下。
线段树能优化的图就是像这道题一样,一个点像一个区间的点连边,或一个区间像一个点连边。一个个连就是\(O(n ^ 2)\)复杂度了,当然承受不起。于是就有了线段树了。
原理很简单,就是把一个连续区间的点合并成线段树上的一个点,这样最多有\(nlogn\)个点。但仅仅这样还不对,所以我们要建两棵树,一个是入度树,一个是出度树。
对于入度树,每一个点要像左右儿子连边,因为如果这个有人像这个点所代表的区间连边,那么也一定能进入他的左右子区间。
对于出度树,左右儿子向父亲连边,因为如果这个点所代表的区间能走到一个点,则他的父亲也一定能到那个点。
而这种连边反过来就不行。
这样我们线段树内部的连边就搞完了,接下来考虑题中的加边。
对于一个点\(v\)向一个区间连边,就在入度树上区间修改,如果到了递归边界,就从\(v\)向这个点的编号连边;对于区间向点连边同理,这里就不说了。
上面提到点的编号,有一个很好的方法就是线段树的节点从\(n + 1\)开始编号,这样原图上的点的编号不会被打乱,点对点的加边还可以正常加。
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
#define enter puts("")
#define space putchar(' ')
#define Mem(a, x) memset(a, x, sizeof(a))
#define In inline
typedef long long ll;
typedef double db;
const ll INF = 1e18;
const db eps = 1e-8;
const int maxn = 5e6 + 5;
const int maxe = 1e7 + 5;
inline ll read()
{
ll ans = 0;
char ch = getchar(), last = ' ';
while(!isdigit(ch)) last = ch, ch = getchar();
while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
if(last == '-') ans = -ans;
return ans;
}
inline void write(ll x)
{
if(x < 0) x = -x, putchar('-');
if(x >= 10) write(x / 10);
putchar(x % 10 + '0');
}
int n, m, s;
struct Edge
{
int nxt, to, w;
}e[maxe];
int head[maxn], ecnt = -1;
In void addEdge(int x, int y, int w)
{
e[++ecnt] = (Edge){head[x], y, w};
head[x] = ecnt;
}
int tIn[maxn], tOut[maxn], l[maxn], r[maxn], tcnt = 0;
In void build(int now, int L, int R)
{
l[now] = L; r[now] = R;
if(L == R)
{
tIn[now] = tOut[now] = L;
return;
}
tIn[now] = ++tcnt; tOut[now] = ++tcnt;
int mid = (L + R) >> 1;
build(now << 1, L, mid);
build(now << 1 | 1, mid + 1, R);
addEdge(tIn[now], tIn[now << 1], 0);
addEdge(tIn[now], tIn[now << 1 | 1], 0);
addEdge(tOut[now << 1], tOut[now], 0);
addEdge(tOut[now << 1 | 1], tOut[now], 0);
}
In void update(int now, int L, int R, int x, int w, bool flg)
{
if(l[now] == L && r[now] == R)
{
if(flg) addEdge(x, tIn[now], w);
else addEdge(tOut[now], x, w);
return;
}
int mid = (l[now] + r[now]) >> 1;
if(R <= mid) update(now << 1, L, R, x, w, flg);
else if(L > mid) update(now << 1 | 1, L, R, x, w, flg);
else update(now << 1, L, mid, x, w, flg), update(now << 1 | 1, mid + 1, R, x, w, flg);
}
#define pr pair<ll, int>
#define mp make_pair
bool in[maxn];
ll dis[maxn];
In void dijkstra(int s)
{
fill(dis + 1, dis + tcnt + 1, INF); dis[s] = 0;
priority_queue<pr, vector<pr>, greater<pr> > q;
q.push(mp(dis[s], s));
while(!q.empty())
{
int now = q.top().second; q.pop();
if(in[now]) continue;
in[now] = 1;
for(int i = head[now], v; ~i; i = e[i].nxt)
{
if(dis[v = e[i].to] > dis[now] + e[i].w)
{
dis[v] = dis[now] + e[i].w;
q.push(mp(dis[v], v));
}
}
}
}
int main()
{
Mem(head, -1);
n = read(), m = read(), s = read();
tcnt = n; build(1, 1, n);
for(int i = 1; i <= m; ++i)
{
int op = read(), x = read();
if(op == 1)
{
int y = read(), w = read();
addEdge(x, y, w);
}
else
{
int L = read(), R = read(), w = read();
update(1, L, R, x, w, op == 2);
}
}
dijkstra(s);
for(int i = 1; i <= n; ++i) write(dis[i] == INF ? -1 : dis[i]), space; enter;
return 0;
}
CF786B Legacy(线段树优化建图)的更多相关文章
- CF786B Legacy 线段树优化建图 + spfa
CodeForces 786B Rick和他的同事们做出了一种新的带放射性的婴儿食品(???根据图片和原文的确如此...),与此同时很多坏人正追赶着他们.因此Rick想在坏人们捉到他之前把他的遗产留给 ...
- Codeforces.786B.Legacy(线段树优化建图 最短路Dijkstra)
题目链接 \(Description\) 有\(n\)个点.你有\(Q\)种项目可以选择(边都是有向边,每次给定\(t,u,v/lr,w\)): t==1,建一条\(u\to v\)的边,花费\(w\ ...
- CF786B Legacy 线段树优化建图
问题描述 CF786B LG-CF786B 题解 线段树优化建图 线段树的一个区间结点代表 \([l,r]\) 区间点. 然后建立区间点的时候就在线段树上建边,有效减少点的个数,从而提高时空效率. 优 ...
- G. 神圣的 F2 连接着我们 线段树优化建图+最短路
这个题目和之前写的一个线段树优化建图是一样的. B - Legacy CodeForces - 787D 线段树优化建图+dij最短路 基本套路 之前这个题目可以相当于一个模板,直接套用就可以了. 不 ...
- BZOJ5017 [SNOI2017]炸弹 - 线段树优化建图+Tarjan
Solution 一个点向一个区间内的所有点连边, 可以用线段树优化建图来优化 : 前置技能传送门 然后就得到一个有向图, 一个联通块内的炸弹可以互相引爆, 所以进行缩点变成$DAG$ 然后拓扑排序. ...
- 【BZOJ3681】Arietta 树链剖分+可持久化线段树优化建图+网络流
[BZOJ3681]Arietta Description Arietta 的命运与她的妹妹不同,在她的妹妹已经走进学院的时候,她仍然留在山村中.但是她从未停止过和恋人 Velding 的书信往来.一 ...
- 【ARC069F】Flags 2-sat+线段树优化建图+二分
Description 数轴上有 n 个旗子,第 ii 个可以插在坐标 xi或者 yi,最大化两两旗子之间的最小距离. Input 第一行一个整数 N. 接下来 N 行每行两个整数 xi, ...
- 【bzoj5017】[Snoi2017]炸弹 线段树优化建图+Tarjan+拓扑排序
题目描述 在一条直线上有 N 个炸弹,每个炸弹的坐标是 Xi,爆炸半径是 Ri,当一个炸弹爆炸时,如果另一个炸弹所在位置 Xj 满足: Xi−Ri≤Xj≤Xi+Ri,那么,该炸弹也会被引爆. 现在 ...
- 【bzoj4699】树上的最短路(树剖+线段树优化建图)
题意 给你一棵 $n$ 个点 $n-1$ 条边的树,每条边有一个通过时间.此外有 $m$ 个传送条件 $(x_1,y_1,x_2,y_2,c)$,表示从 $x_1$ 到 $x_2$ 的简单路径上的点可 ...
- 【BZOJ4276】[ONTAK2015]Bajtman i Okrągły Robin 线段树优化建图+费用流
[BZOJ4276][ONTAK2015]Bajtman i Okrągły Robin Description 有n个强盗,其中第i个强盗会在[a[i],a[i]+1],[a[i]+1,a[i]+2 ...
随机推荐
- [工具]PyCharm激活、注册码无效解决办法
前言 我是个 Pythoner,开发工具一直使用的 JetBrains 的 PyCharm.我师傅告诉过我:一个程序员一定要有一个用的很 6 的 IDE,你的开发效率会提高很多,很多... 我从小白的 ...
- ThreadLocal使用和原理简析
1. 解决共享资源冲突 对于并发工作,需要某种方式来防止两个任务同时访问相同的资源,至少在关键阶段不能出现这种冲突情况. 方法之一就是当资源被一个任务使用时,在其上加锁.第一个访问某项资源的任务必须锁 ...
- LeetCode专题-Python实现之第7题:Reverse Integer
导航页-LeetCode专题-Python实现 相关代码已经上传到github:https://github.com/exploitht/leetcode-python 文中代码为了不动官网提供的初始 ...
- Linux之Nginx使用
一.nginx安装(编译安装) 1,安装需要的依赖库 yum install -y gcc patch libffi-devel python-devel zlib-devel bzip2-devel ...
- 高效开发者是如何个性化VS Code插件与配置的?
2年之前,我放弃了Sublime Text,选择了Visual Studio Code作为代码编辑器. 我每天花在VS Code上的时间长达5~6个小时,因此按照我的需求优化VS Code配置十分必要 ...
- MySQL如何修改密码
以下几种方法可供选择 第一种方式: 最简单的方法就是借助第三方工具Navicat for MySQL来修改,方法如下: 1.登录mysql到指定库,如:登录到test库. 2.然后点击上方“用户”按钮 ...
- 前端入门13-JavaScript进阶之原型
声明 本系列文章内容全部梳理自以下几个来源: <JavaScript权威指南> MDN web docs Github:smyhvae/web Github:goddyZhao/Trans ...
- sqlserver操作geography方法
参考:https://www.cnblogs.com/ytwy/p/5977848.html http://desktop.arcgis.com/zh-cn/arcmap/latest/manage- ...
- IEC104协议规约解析
一.四遥信息体基地址范围 104调度规约有1997年和2002年两个版本,在流程上没有什么变化,02版只是在97版上扩展了遥测.遥信等信息体基体址,区别如下: 类别 1997版基地址 2002版基地址 ...
- virtual table for class
虚函数表 说起虚函数,相信你我都可以自然而然的想到“多态”,因为多态的实现就依赖于虚函数的继承和重写(覆盖).那么,class又或者是object是如何来管理虚函数的呢?你我又会想到虚函数表. 虚函数 ...