本题要求我们支持三种操作:

① 点向点连边。 ② 点向区间连边。 ③ 区间向点连边。

然后跑最短路得出答案。

考虑使用线段树优化建图。

建两颗线段树,入树和出树,每个节点为一段区间的原节点集合。入树内部为儿子向父亲连有向边,出树内部为父亲连有向边,因为入树和出树的叶子节点都为原图中的点,所以两棵树的对应叶子节点连无向边,这些边边权都为\(0\)。

示意图如下,左边为入树,右边为出树。

操作一时,从入树叶子节点向出树叶子节点连边(红色的线)。

操作二时,从入树叶子节点向出树所对应的区间节点连边(蓝色的线)。

操作三时,从入树所对应的区间节点向出树叶子节点连边(绿色的线)。

具体实现细节看代码吧。

记得开\(long\ long\)和开大数组。

\(code:\)

#include<bits/stdc++.h>
#define maxn 800010
#define inf 2000000000
using namespace std;
typedef long long ll;
template<typename T> inline void read(T &x)
{
x=0;char c=getchar();bool flag=false;
while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
if(flag)x=-x;
}
int n,m,s,flag;
struct edge
{
int to,nxt,v;
}e[maxn];
int head[maxn],edge_cnt;
void add(int from,int to,int val)
{
e[++edge_cnt]=(edge){to,head[from],val};
head[from]=edge_cnt;
}
int in_root,out_root,tree_cnt;
int ls[maxn],rs[maxn],in_num[maxn],out_num[maxn];
void build_in(int L,int R,int &cur)
{
cur=++tree_cnt;
if(L==R)
{
in_num[L]=cur;
return;
}
int mid=(L+R)>>1;
build_in(L,mid,ls[cur]);
build_in(mid+1,R,rs[cur]);
add(ls[cur],cur,0),add(rs[cur],cur,0);
}
void build_out(int L,int R,int &cur)
{
cur=++tree_cnt;
if(L==R)
{
out_num[L]=cur;
return;
}
int mid=(L+R)>>1;
build_out(L,mid,ls[cur]);
build_out(mid+1,R,rs[cur]);
add(cur,ls[cur],0),add(cur,rs[cur],0);
}
void modify_in(int L,int R,int l,int r,int pos,int val,int &cur)
{
if(L<=l&&R>=r)
{
add(cur,pos,val);
return;
}
int mid=(l+r)>>1;
if(L<=mid) modify_in(L,R,l,mid,pos,val,ls[cur]);
if(R>mid) modify_in(L,R,mid+1,r,pos,val,rs[cur]);
}
void modify_out(int L,int R,int l,int r,int pos,int val,int &cur)
{
if(L<=l&&R>=r)
{
add(pos,cur,val);
return;
}
int mid=(l+r)>>1;
if(L<=mid) modify_out(L,R,l,mid,pos,val,ls[cur]);
if(R>mid) modify_out(L,R,mid+1,r,pos,val,rs[cur]);
}
ll dis[maxn];
bool vis[maxn];
struct node
{
ll val;
int num;
};
bool operator <(const node &x,const node &y)
{
return x.val>y.val;
}
priority_queue<node> q;
void dijkstra()
{
s=in_num[s];
for(int i=1;i<=tree_cnt;++i) dis[i]=inf;
dis[s]=0;
q.push((node){0,s});
while(!q.empty())
{
node tmp=q.top();
q.pop();
int x=tmp.num;
if(vis[x]) continue;
vis[x]=true;
for(int i=head[x];i;i=e[i].nxt)
{
int y=e[i].to,v=e[i].v;
if(dis[y]>dis[x]+v)
{
dis[y]=dis[x]+v;
q.push((node){dis[y],y});
}
}
}
}
int main()
{
read(n),read(m),read(s);
build_in(1,n,in_root);
build_out(1,n,out_root);
for(int i=1;i<=n;++i)
add(in_num[i],out_num[i],0),add(out_num[i],in_num[i],0);
while(m--)
{
read(flag);
int x,y,l,r,v;
if(flag==1)
{
read(x),read(y),read(v);
add(in_num[x],out_num[y],v);
}
if(flag==2)
{
read(x),read(l),read(r),read(v);
modify_out(l,r,1,n,in_num[x],v,out_root);
}
if(flag==3)
{
read(x),read(l),read(r),read(v);
modify_in(l,r,1,n,out_num[x],v,in_root);
}
}
dijkstra();
for(int i=1;i<=n;++i)
{
if(dis[out_num[i]]==inf) printf("-1 ");
else printf("%lld ",dis[out_num[i]]);
}
return 0;
}

题解 CF786B 【Legacy】的更多相关文章

  1. [题解] CF786B Legacy

    前言 题目链接 题意 有 \(n\) 个点,\(q\) 次连边,以及起点 \(s\) .连边具体分三种: \(1\) \(v\) \(u\) \(w\) 从 \(v\) 到 \(u\) 连一条边. \ ...

  2. CF786B Legacy(线段树优化建边)

    模板题CF786B Legacy 先说算法 如果需要有n个点需要建图 给m个需要建边的信息,从单点(或区间内所有点)向一区间所有点连边 如果暴力建图复杂度\(mn^2\) 以单点连向区间为例,在n个点 ...

  3. CF786B Legacy && 线段树优化连边

    线段树优化连边 要求点 \(x\) 向区间 \([L, R]\) 连边, 一次的复杂度上限为 \(O(n)\) 然后弄成线段树的结构 先父子连边边权为 \(0\) 这样连边就只需要连父亲就可以等效于连 ...

  4. CF786B Legacy 线段树优化建图

    问题描述 CF786B LG-CF786B 题解 线段树优化建图 线段树的一个区间结点代表 \([l,r]\) 区间点. 然后建立区间点的时候就在线段树上建边,有效减少点的个数,从而提高时空效率. 优 ...

  5. 线段树优化建图 || CF786B Legacy

    题面:786B - Legacy 代码: #include<cstdio> #include<cstring> #include<iostream> #includ ...

  6. CF786B Legacy 线段树优化建图 + spfa

    CodeForces 786B Rick和他的同事们做出了一种新的带放射性的婴儿食品(???根据图片和原文的确如此...),与此同时很多坏人正追赶着他们.因此Rick想在坏人们捉到他之前把他的遗产留给 ...

  7. CF786B Legacy(线段树优化建图)

    嘟嘟嘟 省选Day1T2不仅考了字符串,还考了线段树优化建图.当时不会,现在赶快学一下. 线段树能优化的图就是像这道题一样,一个点像一个区间的点连边,或一个区间像一个点连边.一个个连就是\(O(n ^ ...

  8. CF786B Legacy

    思路 线段树优化建图 基本思想就是要把一个区间连边拆成log个节点连边, 然后一颗入线段树,一颗出线段树,出线段树都由子节点向父节点连边(可以从子区间出发),入线段树从父节点向子节点连边(可以到达子区 ...

  9. 【CF786B】Legacy

    题目大意:初始给定 N 个点,支持三种操作:两点之间连边:一个点与一个连续区间编号的点之间连边:一个连续区间内的点和一个点连边,求执行 N 次操作之后的单源最短路. 题解:学会了线段树优化建图. 发现 ...

随机推荐

  1. JDBC知识点总结

    一:JDBC 概述     一.简介        1. JDBC(Java DataBase Connection,Java 数据库连接)是Java语言中用来规范客户端程序如何来访问数据库的应用程序 ...

  2. django 报错处理汇总

    运行 manage.py task时 ,makemigrations抛出以下错误, django.db.utils.OperationalError: (1045, "Access deni ...

  3. Jmeter系列(31)- 获取并使用 JDBC Request 返回的数据

    如果你想从头学习Jmeter,可以看看这个系列的文章哦 https://www.cnblogs.com/poloyy/category/1746599.html 前言 Jmeter 使用 JDBC R ...

  4. Python 简明教程 --- 11,Python 元组

    微信公众号:码农充电站pro 个人主页:https://codeshellme.github.io 软件工程的目标是控制复杂度,而不是增加复杂性. -- Dr. Pamela Zave 目录 我们在上 ...

  5. oracle创建序列,并插入记录

    Oracle序列创建和使用创建序列 语法 CREATE SEQUENCE 序列名 [相关参数] 参数说明 INCREMENT BY  : 序列变化的步进,负值表示递减.(默认1) START WITH ...

  6. 怎样用 I/O流读取txt文件?

    java.io包提供了用来永久保存对象状态的机制,可处理各种类型的流,如文件流.字节流.字符流等,还提供实现可串行化Serializable接口.可处理对象流. Java语言提供3种自动生成的标准流. ...

  7. plsql启动报 Using filter for all users can lead to poor perform

    首先,这个与Oracle配置无关,就是在使用pl/sql左侧树形目录时会看到非常多的和你当前工作无关的表,视图,序列等,导致打开速度慢. ​解决办法:Tools-->Object browser ...

  8. [CF1216E] Numerical Sequence hard version

    题目 The only difference between the easy and the hard versions is the maximum value of k. You are giv ...

  9. 【弹性碰撞问题】POJ 1852 Ants

    Description An army of ants walk on a horizontal pole of length l cm, each with a constant speed of ...

  10. 洛谷 P2648 赚钱

    这道题其实就是求最长路顺便再判断一下正环而已. 这种题肯定要用SPFA的啦,有又正边权(因为最长路所以正边就相当于负边),又是正环(同理,相当于负环),SPFA专治这种问题. 当一个点入队多次的时候, ...