CF-787D-线段树建图+最短路
http://codeforces.com/problemset/problem/787/D
题目大意是给出一个有向图,有N个节点,初始节点在S,询问S到所有点最短路。边的读入方式有三种, 1 u v w 表示 u->v有一条边权为w的边, 2 v l r w ,表示v->[l,r]内的任意一个点支付w即可,
3 v l r w 表示从[l,r]内任意一个点到v支付w即可。直接构图的话可能会出现完全图,被卡死。
一种巧妙的构图方式是,由这些个区间联想到线段树(然而我并没有想到),我们不妨对2,3两种类型建立两颗线段树 他们的叶子节点是共用的(1--N),对于2来说,如果节点v到树上的某个节点x有一条w的边,
就表示v到这个节点所对应的区间的点都可以支付w到达,并且在2的内部所有的父亲都向自己的儿子建立一条边权为0的边,这样如果v能到达x,说明v能到达x所有的子孙节点(支付w),对于3来说只不过反过来了一下思路一样。
建完图之后跑最短路就好了,节点数大约N*10够了。
#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define ULL unsigned long long
#define pii pair<int,int>
#define mid ((L+R)>>1)
#define lc (id<<1)
#define rc (id<<1|1)
#define pb push_back
#define mp make_pair
#define inf 0x3f3f3f3f
#define linf 0xffffffffffff
const int maxn=;
int N,Q,S,T0,T1,CNT;
int ch[maxn*][];
LL d[maxn*];
bool in[maxn*];
int tot,first[maxn*];
struct Edge{int v,w,next;}e[maxn*];
void add(int u,int v,int w){
e[tot].v=v;
e[tot].w=w;
e[tot].next=first[u];
first[u]=tot++;
}
void build1(int &p,int L,int R){
if(L==R) p=L;
else{
p=++CNT;
build1(ch[p][],L,mid),build1(ch[p][],mid+,R);
add(p,ch[p][],),add(p,ch[p][],);
}
} void build2(int &p,int L,int R){
if(L==R) p=L;
else{
p=++CNT;
build2(ch[p][],L,mid),build2(ch[p][],mid+,R);
add(ch[p][],p,),add(ch[p][],p,);
}
}
void insert1(int id,int L,int R,int v,int l,int r,int w){
if(L>=l&&R<=r){
add(v,id,w);
return;
}
if(l<=mid)insert1(ch[id][],L,mid,v,l,r,w);
if(r>mid)insert1(ch[id][],mid+,R,v,l,r,w);
} void insert2(int id,int L,int R,int v,int l,int r,int w){
if(L>=l&&R<=r){
add(id,v,w);
return;
}
if(l<=mid)insert2(ch[id][],L,mid,v,l,r,w);
if(r>mid)insert2(ch[id][],mid+,R,v,l,r,w);
}
void spfa(){
for(int i=;i<=CNT;++i)d[i]=linf;
memset(in,,sizeof(in));
queue<int>q;
q.push(S);
in[S]=;
d[S]=;
while(!q.empty()){
int u=q.front();
q.pop();
for(int i=first[u];~i;i=e[i].next){
if(d[e[i].v]>d[u]+e[i].w){
d[e[i].v]=d[u]+e[i].w;
if(!in[e[i].v]){
q.push(e[i].v);
}
}
}
}
for(int i=;i<=N;++i) printf("%lld%c",d[i]==linf?-:d[i],i==N?'\n':' ');
}
int main()
{
memset(first,-,sizeof(first));
tot=;
scanf("%d%d%d",&N,&Q,&S);
CNT=N;
build1(T0,,N);
build2(T1,,N);
int opt,u,v,w,l,r;
while(Q--){
scanf("%d",&opt);
if(opt==){
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
}
else{
scanf("%d%d%d%d",&v,&l,&r,&w);
if(opt==){
insert1(T0,,N,v,l,r,w);
}
else{
insert2(T1,,N,v,l,r,w);
}
}
}
spfa();
return ;
}
/*0 -1-112
0 -1 -1 12
*/
CF-787D-线段树建图+最短路的更多相关文章
- 【转】Codeforces Round #406 (Div. 1) B. Legacy 线段树建图&&最短路
B. Legacy 题目连接: http://codeforces.com/contest/786/problem/B Description Rick and his co-workers have ...
- BZOJ4383/LuoGuP3588 Pustynia/PUS 线段树建图优化
我会告诉你我看了很久很久才把题目看懂吗???怀疑智商了 原来他给的l,r还有k个数字都是下标... 比如给了一个样例 l, r, k, x1,x2,x3...xk,代表的是一个数组num[l]~num ...
- HDU5669 Road 分层最短路+线段树建图
分析:(官方题解) 首先考虑暴力,显然可以直接每次O(n^2) 的连边,最后跑一次分层图最短路就行了. 然后我们考虑优化一下这个连边的过程 ,因为都是区间上的操作,所以能够很明显的想到利用线段树来维 ...
- 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 (线段树建图dij)
D. Legacy time limit per test 2 seconds memory limit per test 256 megabytes input standard input out ...
- POJ 2374 线段树建图+Dijkstra
题意: 思路: 线段树+Dijkstra(要堆优化的) 线段树要支持打标记 一个栅栏 拆成两个点 :左和右 新加一个栅栏的时候 看看左端点有没有被覆盖过 如果有的话 就分别从覆盖的那条线段的左右向当前 ...
- CodeForces 786B Legacy(线段树优化建图+最短路)
[题目链接] http://codeforces.com/problemset/problem/786/B [题目大意] 给出一些星球,现在有一些传送枪,可以从一个星球到另一个星球, 从一个星球到另一 ...
- G. 神圣的 F2 连接着我们 线段树优化建图+最短路
这个题目和之前写的一个线段树优化建图是一样的. B - Legacy CodeForces - 787D 线段树优化建图+dij最短路 基本套路 之前这个题目可以相当于一个模板,直接套用就可以了. 不 ...
- B - Legacy CodeForces - 787D 线段树优化建图+dij最短路 基本套路
B - Legacy CodeForces - 787D 这个题目开始看过去还是很简单的,就是一个最短路,但是这个最短路的建图没有那么简单,因为直接的普通建图边太多了,肯定会超时的,所以要用线段树来优 ...
随机推荐
- HDU 4323 Magic Number(编辑距离DP)
http://acm.hdu.edu.cn/showproblem.php?pid=4323 题意: 给出n个串和m次询问,每个询问给出一个串和改变次数上限,在不超过这个上限的情况下,n个串中有多少个 ...
- 一:requests爬虫基础
一,什么是爬虫? 描述: 本质是一个自动化程序,一个模拟浏览器向某一个服务器发送请求获取响应资源的过程. 爬虫的基本流程 robots.txt协议 编写一个robots.txt的协议文件来约束爬虫程序 ...
- 实体entity、JavaBean、Model、POJO、domain的区别
实体entity.JavaBean.Model.POJO.domain的区别Java Bean.POJO. Entity. VO , 其实都是java 对象,只不过用于不同场合罢了. 按照 Sprin ...
- 日期时间函数 mysql 和sqlserver 中对于常用函数的日期和时间函数的区别
1. sqlserver中获取时间用getdate(),默认返回格式是2019-01-21 13:58:33.053,具体的年月日,时分秒毫米,年月日之间用短线连接,时分秒之间用冒号连接,秒和毫米之间 ...
- sklearn中的train_test_split (随机划分训练集和测试集)
官方文档:http://scikit-learn.org/stable/modules/generated/sklearn.model_selection.train_test_split.html ...
- 记录一次在centos下使用gmp的悲伤
有个作业是需要在linux下做的,并且需要用到gmp这个 library : 我使用的是虚拟机centos7.很久没碰过linux了,忘得差不多了,一点点百度出来的 1. 首先检查是否已存在gmp库 ...
- 你真的了解restful api吗?
前言 在以前,一个网站的完成总是“all in one”,页面,数据,渲染全部在服务端完成,这样做的最大的弊端是后期维护,扩展极其痛苦,开发人员必须同时具备前后端知识.于是慢慢的后来兴起了前后端分离的 ...
- 《剑指offer》第四十九题(丑数)
// 面试题49:丑数 // 题目:我们把只包含因子2.3和5的数称作丑数(Ugly Number).求按从小到 // 大的顺序的第1500个丑数.例如6.8都是丑数,但14不是,因为它包含因子7. ...
- C# DataTable 通过Linq分组
datatable我们是经常使用到的,但是需要对数据进行分组,具体代码如下: var result = dt.AsEnumerable().GroupBy(f => new { type = f ...
- R语言画点状误差线
现在项目需要R语言做几个线性拟合,画一些点图,突然需要画误差线,网上找了下,可以用代码实现..效果如下 xx1<-c(xxxxxx,xxxx,xxxxx) yy1<-c(xxxxxx,xx ...