CF 787D Legacy(线段树思想构图+最短路)
2 seconds
256 megabytes
standard input
standard output
Rick and his co-workers have made a new radioactive formula and a lot of bad guys are after them. So Rick wants to give his legacy to Morty before bad guys catch them.
There are n planets in their universe numbered from 1 to n. Rick is in planet number s (the earth) and he doesn't know where Morty is. As we all know, Rick owns a portal gun. With this gun he can open one-way portal from a planet he is in to any other planet (including that planet). But there are limits on this gun because he's still using its free trial.
By default he can not open any portal by this gun. There are q plans in the website that sells these guns. Every time you purchase a plan you can only use it once but you can purchase it again if you want to use it more.
Plans on the website have three types:
- With a plan of this type you can open a portal from planet v to planet u.
- With a plan of this type you can open a portal from planet v to any planet with index in range [l, r].
- With a plan of this type you can open a portal from any planet with index in range [l, r] to planet v.
Rick doesn't known where Morty is, but Unity is going to inform him and he wants to be prepared for when he finds and start his journey immediately. So for each planet (including earth itself) he wants to know the minimum amount of money he needs to get from earth to that planet.
The first line of input contains three integers n, q and s (1 ≤ n, q ≤ 105, 1 ≤ s ≤ n) — number of planets, number of plans and index of earth respectively.
The next q lines contain the plans. Each line starts with a number t, type of that plan (1 ≤ t ≤ 3). If t = 1 then it is followed by three integers v, u and w where w is the cost of that plan (1 ≤ v, u ≤ n, 1 ≤ w ≤ 109). Otherwise it is followed by four integers v, l, r and w where w is the cost of that plan (1 ≤ v ≤ n, 1 ≤ l ≤ r ≤ n, 1 ≤ w ≤ 109).
In the first and only line of output print n integers separated by spaces. i-th of them should be minimum money to get from earth to i-th planet, or - 1 if it's impossible to get to that planet.
3 5 1
2 3 2 3 17
2 3 2 2 16
2 2 2 3 3
3 3 1 1 12
1 3 3 17
0 28 12
4 3 1
3 4 1 3 12
2 2 3 4 10
1 2 4 16
0 -1 -1 12
In the first sample testcase, Rick can purchase 4th plan once and then 2nd plan in order to get to get to planet number 2.
题目链接:CF 787D
很脑洞的一道题,比较好的做法是用线段树分割区间的思想,把1-n看成区间构建两颗线段树A和B,然后把所有的子区间都看成一个点,这样后面的加边就是对这些区间加边了,构建好A和B,A父子节点之间自底向上加有向边,B树自顶向下加有向边,然后把B树的子节点加无向边到对应的A树的子节点,代表这些点可以推出(到达)哪些点,由于一开始在子节点s(A[s]还是B[s]无所谓,两者本来就是强连通的),哪里都不能去,因此最后要检查的就是B树的子节点的dis值(在A数的话哪里都可以)。
然后就是三种区间操作
1:u->v,加边$<A的叶子节点u,B的叶子节点v,w>$
2:u->[l,r],加边$<A的叶子节点u,\{B树中[l,r]区间对应的节点集合\},w>$
3:[l,r]->v,加边$<\{A树中[l,r]区间对应的节点集合\},B树的叶子节点v,w>$
这样一来三种边都不会多也不会少刚好可以到达正确的点。然后从B[s]的跑最短路即可,最后检查B[i]的dis即可,当然一开始要把A、B树的叶子节点记录下来方便后面加边使用
边数最坏情况应该是每一层左右均取两个区间,一直递归下去,有$log_{2}N$层,因此边数大约是$O(4*q*log_{2}N+2N)$
代码:
#include <stdio.h>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <bitset>
#include <string>
#include <stack>
#include <cmath>
#include <queue>
#include <set>
#include <map>
using namespace std;
#define INF 0x3f3f3f3f
#define LC(x) (x<<1)
#define RC(x) ((x<<1)+1)
#define MID(x,y) ((x+y)>>1)
#define fin(name) freopen(name,"r",stdin)
#define fout(name) freopen(name,"w",stdout)
#define CLR(arr,val) memset(arr,val,sizeof(arr))
#define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
typedef pair<int, int> pii;
typedef long long LL;
const double PI = acos(-1.0);
const int N = 1e5 + 7;
struct edge
{
int to, nxt;
LL w;
edge() {}
edge(int _to, int _nxt, LL _w): to(_to), nxt(_nxt), w(_w) {}
} E[N * 68];
int head[N << 2], tot;
LL d[N << 2];
bitset < N << 2 > vis;
int id[2][N << 2], sz;
vector<int>st;
int A[N], B[N]; void init()
{
CLR(head, -1);
tot = 0;
sz = 0;
}
inline void add(int s, int t, LL w)
{
E[tot] = edge(t, head[s], w);
head[s] = tot++;
}
void build(int k, int l, int r, int o)
{
id[o][k] = ++sz;
if (l == r)
{
if (o)
A[l] = id[o][k];
else
B[l] = id[o][k];
return ;
}
else
{
int mid = MID(l, r);
build(LC(k), l, mid, o);
build(RC(k), mid + 1, r, o);
if (o) //A树自底向上
{
add(id[o][LC(k)], id[o][k], 0);
add(id[o][RC(k)], id[o][k], 0);
}
else//B树自顶向下
{
add(id[o][k], id[o][LC(k)], 0);
add(id[o][k], id[o][RC(k)], 0);
}
}
}
void Findset(int k, int l, int r, int ql, int qr, int o)
{
if (ql <= l && r <= qr)
st.push_back(id[o][k]);
else
{
int mid = MID(l, r);
if (qr <= mid)
Findset(LC(k), l, mid, ql, qr, o);
else if (ql > mid)
Findset(RC(k), mid + 1, r, ql, qr, o);
else
Findset(LC(k), l, mid, ql, mid, o), Findset(RC(k), mid + 1, r, mid + 1, qr, o);
}
}
void SPFA(int s)
{
queue<int>Q;
Q.push(s);
vis.reset();
CLR(d, INF);
d[s] = 0;
while (!Q.empty())
{
int u = Q.front();
Q.pop();
vis[u] = 0;
for (int i = head[u]; ~i; i = E[i].nxt)
{
int v = E[i].to;
if (d[v] > d[u] + E[i].w)
{
d[v] = d[u] + E[i].w;
if (!vis[v])
{
vis[v] = 1;
Q.push(v);
}
}
}
}
}
int main(void)
{
int n, q, s, i, ops;
while (~scanf("%d%d%d", &n, &q, &s))
{
init();
build(1, 1, n, 1);
build(1, 1, n, 0);
for (i = 1; i <= n; ++i)
{
add(A[i], B[i], 0);
add(B[i], A[i], 0);
}
for (i = 0; i < q; ++i)
{
scanf("%d", &ops);
if (ops == 1)
{
int u, v;
LL w;
scanf("%d%d%I64d", &u, &v, &w);
add(A[u], B[v], w);
}
else if (ops == 2)
{
int u, l, r;
LL w;
scanf("%d%d%d%I64d", &u, &l, &r, &w);
st.clear();
Findset(1, 1, n, l, r, 0);
for (auto &x : st)
add(A[u], x, w);
}
else if (ops == 3)
{
int v, l, r;
LL w;
scanf("%d%d%d%I64d", &v, &l, &r, &w);
st.clear();
Findset(1, 1, n, l, r, 1);
for (auto &x : st)
add(x, B[v], w);
}
}
SPFA(B[s]);
for (i = 1; i <= n; ++i)
printf("%I64d%c", d[B[i]] == 0x3f3f3f3f3f3f3f3f ? -1 : d[B[i]], " \n"[i == n]);
}
return 0;
}
CF 787D Legacy(线段树思想构图+最短路)的更多相关文章
- Codeforces 787D. Legacy 线段树建模+最短路
D. Legacy time limit per test:2 seconds memory limit per test:256 megabytes input:standard input out ...
- codeforces 787D - Legacy 线段树优化建图,最短路
题意: 有n个点,q个询问, 每次询问有一种操作. 操作1:u→[l,r](即u到l,l+1,l+2,...,r距离均为w)的距离为w: 操作2:[l,r]→u的距离为w 操作3:u到v的距离为w 最 ...
- Codeforces 787D Legacy 线段树 最短路
题意: 有\(n(1 \leq n \leq 10^5)\)个点,\(q(1 \leq q \leq 10^5)\)条路和起点\(s\) 路有三种类型: 从点\(v\)到点\(u\)需要花费\(w\) ...
- 【转】Codeforces Round #406 (Div. 1) B. Legacy 线段树建图&&最短路
B. Legacy 题目连接: http://codeforces.com/contest/786/problem/B Description Rick and his co-workers have ...
- [CF787D]遗产(Legacy)-线段树-优化Dijkstra(内含数据生成器)
Problem 遗产 题目大意 给出一个带权有向图,有三种操作: 1.u->v添加一条权值为w的边 2.区间[l,r]->v添加权值为w的边 3.v->区间[l,r]添加权值为w的边 ...
- CF786B Legacy && 线段树优化连边
线段树优化连边 要求点 \(x\) 向区间 \([L, R]\) 连边, 一次的复杂度上限为 \(O(n)\) 然后弄成线段树的结构 先父子连边边权为 \(0\) 这样连边就只需要连父亲就可以等效于连 ...
- Codeforces Round #406 (Div. 1) B. Legacy 线段树建图跑最短路
B. Legacy 题目连接: http://codeforces.com/contest/786/problem/B Description Rick and his co-workers have ...
- Codeforces Round #406 (Div. 2) D. Legacy 线段树建模+最短路
D. Legacy time limit per test 2 seconds memory limit per test 256 megabytes input standard input out ...
- CodeForces - 786B Legacy (线段树+DIjkstra+思维)
题意:给N个点和Q条选项,有三种类型的选项:1.从u到v花费w修建一条路:2.从u到下标区间为[L,R]的点花费w修建一条路; 3.从下标区间为[L,R]的点到u花费w修建一条路. 然后求起点s到其余 ...
随机推荐
- datatable行内内容太长,有时不自动换行解决方法
加一个css属性即可 style = "word-wrap:break-word;" js代码: "render": function (data, type, ...
- 红帽CentOS7 密码破解
1.在启动的时候按住方向键停留在内核选项页面,在内核选项出按e键 2.进入到另一个页面后,寻找到以linux16开头的地方,按end到行后,输入空格,然后输入rd.break console=tty0 ...
- java-访问控制修饰符
访问权限 public 任何情况都可以访问 默认包 本包范围内可以访问到 protect 同一个包里的所有类所可以访问:所有子类(子类可以不和父类在同一个包)都可以访问 privat ...
- 手机连上同一个局域网的PC,修改项目的vhost配置
<VirtualHost 172.16.6.100:80> DocumentRoot "D:\phpStudy\WWW\mywork\many_school" Serv ...
- stark组件(11):组合搜索
效果图: 新增函数和类 Option 获取字段的对象或元组 SearchGroupRow 封装数据,展示到前端 get_search_group 获取组合搜索的字段 get_search_group_ ...
- POJ 1854 贪心(分治)
Evil Straw Warts Live Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 1144 Accepted: ...
- strchr函数的用法
原型: char *strchr(const char *s,char c); #include<string.h> 查找字符串s中首次出现字符c的位置,返回首次出现c的位置的指针,如果s ...
- ElasticSearch 之 Client
在使用ElasticSearch的时候,我们需要与Cluster通信,Java版本的API提供了几种方式来构造Client,进而通过Client操作Cluster. 1)使用Node与clusto ...
- 关于原生JS获取class,ID等属性的一些封装
一.传统上获取是通过document.getElementById获取元素的ID属性,通过总结与学习总结一下获取元素class以及id属性的一些封装; 1.创建构造函数,这里面不需要多解释什么:(主要 ...
- 剑指Offer - 九度1519 - 合并两个排序的链表
剑指Offer - 九度1519 - 合并两个排序的链表2013-11-30 22:04 题目描述: 输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则.(hi ...