题意:给N个点和Q条选项,有三种类型的选项:1.从u到v花费w修建一条路;2.从u到下标区间为[L,R]的点花费w修建一条路; 3.从下标区间为[L,R]的点到u花费w修建一条路。

然后求起点s到其余点的最短路。

如果直接暴力建图,建图本身就会超时。对于区间上的操作,考虑用线段树解决。线段树上的结点本身就能代表一段区间的点,所以在建图时,用树上的结点充当中间结点。(有点网络流的思想?)

因为要建一张有向图,所以图的点到树上结点要连边,反之亦然;但是在一棵线段树上双向连边就不能对所有的点跑最短路了(因为图中的点可能会在树上找到权值为0的回路回到自己)。

所以再建一棵线段树去表示反向连边的关系。

对每个树上结点从N+1开始编号,将其与之维护的区间中的点连一条花费为0的边。每次更新就是用把给定区间[L,R]囊括的所有树上结点与给定的u连边。操作2和操作3分别对应两棵线段树的结点。

#include<bits/stdc++.h>
#define lson rt<<1
#define rson rt<<1|1
#define Lson l,m,lson
#define Rson m+1,r,rson
using namespace std;
typedef long long LL;
const int maxn = 4e5+;
const LL INF = (1LL)<<;
struct Edge{
int to,next;
LL w;
}edges[maxn<<];
int head[maxn<<],tot;
int ID[maxn<<],rID[maxn<<];
int id; void init(int N)
{
memset(head,-,sizeof(head));
tot=;
id = N;
} void AddEdge(int u,int v,LL w){
edges[tot] = (Edge){v,head[u],w};
head[u] = tot++;
} void build(int l,int r,int rt,bool flag)
{
if(!flag) ID[rt] = ++id;
else rID[rt] = ++id;
if(!flag) {for(int i=l;i<=r;++i) AddEdge(ID[rt],i,);}
else {for(int i=l;i<=r;++i) AddEdge(i,rID[rt],);}
if(l==r) return;
int m = (l+r)>>;
build(Lson,flag);
build(Rson,flag);
} void update(int L,int R,LL w,int u,int l,int r,int rt,bool flag)
{
if(L<=l && R>=r){
if(!flag)AddEdge(u,ID[rt],w);
else AddEdge(rID[rt],u,w);
return;
}
int m =(l+r)>>;
if(L<=m) update(L,R,w,u,Lson,flag);
if(R>m) update(L,R,w,u,Rson,flag);
} LL d[maxn<<];
bool used[maxn<<];
struct HeapNode{
LL d;
int u;
bool operator <(const HeapNode & rhs) const {return d > rhs.d;}
};
void dijkstra(int s){
memset(used,,sizeof(used));
priority_queue<HeapNode> Q;
for(int i=;i<=id;++i) d[i]=INF;
d[s]=;
Q.push((HeapNode){,s});
while(!Q.empty()){
HeapNode x =Q.top();Q.pop();
int u =x.u;
if(used[u]) continue;
used[u]= true;
for(int i=head[u];~i;i=edges[i].next){
Edge & e = edges[i];
if(d[e.to] > d[u] + e.w){
d[e.to] = d[u] +e.w;
Q.push((HeapNode){d[e.to],e.to});
}
}
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int T,N,M,q,s,u,v,op,L,R;
LL w;
while(scanf("%d%d%d",&N,&q,&s)==){
init(N);
build(,N,,);
build(,N,,);
while(q--){
scanf("%d",&op);
if(op==){
scanf("%d%d%lld",&u,&v,&w);
AddEdge(u,v,w);
}
else if(op==){
scanf("%d%d%d%lld",&u,&L,&R,&w);
update(L,R,w,u,,N,,);
}
else{
scanf("%d%d%d%lld",&u,&L,&R,&w);
update(L,R,w,u,,N,,);
}
}
dijkstra(s);
for(int i=;i<=N;++i)
printf("%lld%c",d[i]==INF?-:d[i],i==N?'\n':' ');
}
return ;
}

CodeForces - 786B Legacy (线段树+DIjkstra+思维)的更多相关文章

  1. Codeforces.786B.Legacy(线段树优化建图 最短路Dijkstra)

    题目链接 \(Description\) 有\(n\)个点.你有\(Q\)种项目可以选择(边都是有向边,每次给定\(t,u,v/lr,w\)): t==1,建一条\(u\to v\)的边,花费\(w\ ...

  2. Codeforces 786B. Legacy 线段树+spfa

    题目大意: 给定一个\(n\)的点的图.求\(s\)到所有点的最短路 边的给定方式有三种: \(u \to v\) \(u \to [l,r]\) \([l,r] \to v\) 设\(q\)为给定边 ...

  3. Codeforces 787D. Legacy 线段树建模+最短路

    D. Legacy time limit per test:2 seconds memory limit per test:256 megabytes input:standard input out ...

  4. 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 最 ...

  5. Codeforces 787D Legacy 线段树 最短路

    题意: 有\(n(1 \leq n \leq 10^5)\)个点,\(q(1 \leq q \leq 10^5)\)条路和起点\(s\) 路有三种类型: 从点\(v\)到点\(u\)需要花费\(w\) ...

  6. 786B - Legacy(线段树 + 最短路)线段树优化建图

    题意: 就是给定一张n nn个点的图,求源点s ss到每个点的单源最短路.这张图共有q组边,连边方式有3种: a→b ,边权为w的单向边:a→[l,r] ,即a到连续区间[l,r]中的每一个点都有一条 ...

  7. [Educational Codeforces Round 81 (Rated for Div. 2)]E. Permutation Separation(线段树,思维,前缀和)

    [Educational Codeforces Round 81 (Rated for Div. 2)]E. Permutation Separation(线段树,思维,前缀和) E. Permuta ...

  8. CodeForces 786B Legacy(线段树优化建图+最短路)

    [题目链接] http://codeforces.com/problemset/problem/786/B [题目大意] 给出一些星球,现在有一些传送枪,可以从一个星球到另一个星球, 从一个星球到另一 ...

  9. Codeforces 786B Legacy(线段树优化建图)

    题目链接  Legacy 首先对于输入的$n$,建立一棵线段树. 显然线段树有大概$2n$个结点,每个节点对应一段区间 我们把这$2n$个结点加入我们的无向图中,一起跑最短路. 具体连边方案: 我们把 ...

随机推荐

  1. 安装第三方模块时遇到Python version 2.7 required, which was not found

    ## script to register Python 2.0 or later for use with win32all# and other extensions that require P ...

  2. C++学习之拷贝构造函数篇

    一.拷贝构造函数的声明 Array(const Array & arr); 二.拷贝构造函数的实现分为两种,即是深拷贝和浅拷贝. 1.浅拷贝 代码例如以下: class Array { pub ...

  3. 【翻译自mos文章】使用asm来部署 超大数据库(10TB到PB 范围)--针对oracle 10G

    使用asm来部署 超大数据库(10TB到PB 范围) 參考原文: Deployment of very large databases (10TB to PB range) with Automati ...

  4. FreeRTOS系列第17篇---FreeRTOS队列

    本文介绍队列的基本知识,具体源代码分析见<FreeRTOS高级篇5---FreeRTOS队列分析> 1.FreeRTOS队列 队列是基本的任务间通讯方式.能够在任务与任务间.中断和任务间传 ...

  5. js事件循环机制(Event Loop)

    javascript从诞生之日起就是一门  单线程的  非阻塞的  脚本语言,单线程意味着,javascript代码在执行的任何时候,都只有一个主线程来处理所有的任务,非阻塞靠的就是 event lo ...

  6. db2 clob dbclob

    DB2有三种类型的大字段: clob(Character Large OBjects ) 适用于存放单字节的字符串,当我们要保存的字符长度超过varchar的最大长度(32K)时,我们就要考虑使用cl ...

  7. raw_input() 与 input()对比

    转载来自http://www.cnblogs.com/way_testlife/archive/2011/03/29/1999283.html 这两个均是 python 的内建函数,通过读取控制台的输 ...

  8. asp.net session丢失的解决方法小结

    现在我就把原因和解决办法写出来. ASP.NET Session丢失原因: 由于Asp.net程序是默认配置,所以Web.Config文件中关于Session的设定如下: < sessionSt ...

  9. C++三大函数(The Big Three)

    本文用Markdown编辑,这里对Markdown的支持不完善,更好的阅读体验请移步:我的Markdown文本 C++三大函数: 析构函数 复制构造函数 operator= 析构函数 函数模样:~S( ...

  10. oracle游标:查询并打印员工的姓名和薪水

    --查询并打印员工的姓名和薪水 --set serveroutput on /* 1.光标的属性 %found:假设取到了记录就是true否则是false: %notfound: */ declare ...