首页 > 其他分享 >题解 AT5635 Shortest Path on a Line(线段树优化建图)

题解 AT5635 Shortest Path on a Line(线段树优化建图)

时间:2022-08-30 23:01:15浏览次数:94  
标签:int 题解 线段 tot AT5635 建图 gc 区间

题解 AT5635 Shortest Path on a Line

Description

题目传送门

题面翻译

有一张有 \(N\) 个点,编号为 \(1 - N\) 的无向图。

做 \(M\) 次操作,每次操作给出三个正整数 \(L,R,C\),对于每对 \(≥L\) 且 \(≤R\) 的整数对 \((S,T)\) ,在 \((S,T)\) 之间添加一条长度为 \(C\) 的边

完成操作后,找出操作后无向图的最短路。

数据范围

  • $ N,M\ \leq\ 10^5 $

Solution

线段树优化建图裸题。

看到区间向区间连边,显然暴力处理是 \(O(MN)\) 的,时间超限。

那么可以想到处理区间问题的常用工具:线段树。

不会线段树优化建图?模板 CF786B

和模板题一样,我们先建好入树和出树。

模板题是点到区间和区间到点加边,而本题是区间向区间加边。

这个时候我们可以新建一个节点,将出树区间向这个节点连边,这个点再向入树区间连边,就转化为了模板题。

然后剩下的就是最短路板子,我用的堆优化的 Dijkstra。

Code

#include <bits/stdc++.h>
#define gc() getchar()
using namespace std;
typedef long long ll;
// 快读
template <typename T> void rd(T &x){
	T f=1;x=0;char c=gc();
	for(;!isdigit(c);c=gc())if(c=='-')f=-1;
	for(;isdigit(c);c=gc())x=(x<<1)+(x<<3)+(c^48);
	x*=f;
}
const int MAXN=2e6+5;// 数组大小,开太小会 RE
// 链式前向星存图 
int n,m,cnt,hd[MAXN];
struct nd{
	int nxt,v,w;
}g[MAXN<<1];
inline void add(int u,int v,int w){
	g[++cnt].nxt=hd[u],g[cnt].v=v,g[cnt].w=w,hd[u]=cnt;
}
// 线段树
int tot,in[MAXN],out[MAXN];// tot 从 n 开始,in 存的是入树节点对应的图中节点编号,out 同理
struct sgt{
	int l,r;
}t[MAXN];
// 建树
inline void build(int o,int l,int r){
	t[o].l=l,t[o].r=r;
	if(l==r){
		in[o]=out[o]=l;// 如果是叶子节点,那么对应图中节点编号就是其下标,入树出树共用
		return;
	}
	int mid=l+r>>1;
	in[o]=++tot,out[o]=++tot;// 存储 o 代表的区间对应的图中节点
	build(o<<1,l,mid);
	build(o<<1|1,mid+1,r);// 递归建树
	add(out[o<<1],out[o],0);
	add(out[o<<1|1],out[o],0);// 将出树从子节点向父节点连零边
	add(in[o],in[o<<1],0);
	add(in[o],in[o<<1|1],0);// 将入树从父节点向子节点连零边
}
// 加边
inline void addedge(int o,int l,int r,int u,int w){
	if(t[o].l>=l&&t[o].r<=r){
		add(out[o],u,0);// 从出树区间向新建节点连零边
		add(u,in[o],w);// 从新建节点向入树区间连长度为 w 的边
		return;
	}
	int mid=t[o].l+t[o].r>>1;
    // 递归加边
	if(l<=mid)addedge(o<<1,l,r,u,w);
	if(r>mid)addedge(o<<1|1,l,r,u,w);
}
// Dijkstra
const ll inf=0x3f3f3f3f3f3f3f3f;
ll d[MAXN];
int vis[MAXN];
// 堆优化
struct pq{
	int v;ll w;
	pq(){}
	pq(int _v,ll _w){v=_v,w=_w;}
	bool operator<(const pq &a)const{return w>a.w;}
};
priority_queue<pq>q;
inline void dij(){
	memset(d,0x3f,sizeof(d));
	d[1]=0;q.push(pq(1,0));
	while(!q.empty()){
		pq x=q.top();q.pop();
		int u=x.v;if(vis[u])continue;
		vis[u]=1;
		for(int i=hd[u];i;i=g[i].nxt){
			int v=g[i].v,w=g[i].w;
			if(d[v]>d[u]+w)d[v]=d[u]+w,q.push(pq(v,d[v]));
		}
	}
}

int main(){
	//freopen(".in","r",stdin);
	//freopen(".out","w",stdout);
	rd(n),rd(m);tot=n;// tot 从 n 开始,避免与叶子节点重复
	build(1,1,n);// 别忘了建树
	for(int i=1;i<=m;++i){
		int l,r,w;
		rd(l),rd(r),rd(w);
		addedge(1,l,r,++tot,w);// ++tot 新建节点
	}
	dij();
	printf("%lld\n",d[n]==inf?-1:d[n]);// 记得开 long long
	return 0;
}

by sysong

\(2022.8.30\)

标签:int,题解,线段,tot,AT5635,建图,gc,区间
From: https://www.cnblogs.com/sysong2006/p/16641279.html

相关文章

  • Jenkins 踩坑 | job 创建、参数化、定时构建及时区偏差问题解决
    ⬇️点击“下方链接”,提升测试核心竞争力!>>更多技术文章分享和免费资料领取1)启动Jenkins后在首页点击"开始创建一个新任务"。2)输入任务名称,选择自由风格,点击“确定”。......
  • 【题解】SP8836 SEQ7
    LinkPrologue大大滴诈骗题/ohDescription定义数列\(\{g(n)\}_{n\in\mathbbN^*}\):\(g(1)=1\),\(g(n)\)为\(n\)在数列中出现的次数。给定\(n\)(\(n\le10^{13}\)),......
  • AtCoder Beginner Contest 266 一句话题解
    AandBsbt,不讲。C垃圾计算几何,问是不是一个凸包,搞份板子交就可以了。D简单dp,令\(f(i,j)\)表示第\(i\)个时间在第\(j\)个位置的最大价值,从上一个时间转移,可以......
  • 2021年 西南石油大学超算与并行计算团队南充校区分队 第二届招新赛题解
      2021年SWPU(南充)超算团队招新赛总体难度并不是很大,大部分题目考察的是基本的编程能力,题目中涉及到了一些并行计算相关的名词和知识,选手在参加比赛的同时,既能够展示......
  • 洛谷 P6862 [RC-03] 随机树生成器 绿 题解
    前言模数要模\(1e9+9\)!!模数要模\(1e9+9\)!!模数要模\(1e9+9\)!!结论\(n\)个点的树的形态有\((n-1)!\)个,对于节点\(k\),它的所有度数和为\((n-1)!\left(\sum\limits_{......
  • [Atcoder]ABC266题解
    C-ConvexQuadrilateral计算几何给定平面内四个点,要求判断它们组成的四边形是否是凸四边形法一:凸四边形的两条对角线将其分成两个三角形分成的两个三角形面积相加......
  • [POJ1062]昂贵的聘礼题解
    [POJ1062]昂贵的聘礼题目链接【题目大意】现有n个物品,每个物品价格为vi,同时可以用其他物品减免价格(当然,你必须拥有该物品).问如何购买可以使得到物品1的花费最少.此外,还......
  • CF1455G Forbidden Value 题解
    CF1455GForbiddenValue已知初始值\(x=0\),给定下面2种命令:set\(y\)\(v\),令\(x=y\),或花费\(v\)元钱删除该命令;if\(y\)...end,如果\(x==y\),执行if...end中的命令,否......
  • 题解 树套树
    题面二叉查找树(BST)是一种简单的数据结构,本题默认你已经熟悉BST的插入和查询两种操作。给你一棵树,每个节点有一个BST。有以下两种操作:\(u,v,k\):在路径\((u,v)\)上每......
  • AtCoder Beginner Contest 266 题解
    只有ABCDEFG的题解。A模拟。代码voidmian(){strings;cin>>s;intpos=int(s.size())/2;cout<<s[pos]<<endl;}B模拟,注意longlong。......