Legacy (线段树优化建图)
题目链接:Legacy - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
题解:
考虑题目中一个点向区间连边,如真的对区间中的每一点分别连边后跑最短路,时间空间都要炸。
因为是一个点向区间连边,考虑线段树。
1到n构造两颗区间线段数
观察上图(从网上搬的)
两颗线段树,一颗入树父亲向儿子连边,用来优化指向叶子的边(左边的树)一颗出树儿子向父亲连边用来优化从叶子指出的点(右边的树)两棵树完全相同。
每个叶子为表示一个星球(可以理解为拆点处理入边和出边),对应的星球之间连一条边,边权为0,因为一个点到自己不花费代价(图中黄色的边)
对于题中给出的操作,操作一可以与操作二等价(也可以与操作三等价)理解为一个点可以去一个区间。
操作二从第二个树上的叶子v向第一颗树上对应的区间连边(与线段树操作相同)
操作三从第一个树上的叶子v向第二颗颗树上对应的区间连边(与上图不太相同,可以自己画图理解)
最后从s点跑最短路
#include <bits/stdc++.h>
using namespace std;
const int N=5e5+10;
const int M=4e6+10;
#define int long long//数据比较大,会爆int
int tot,n,q,s,cnt,root,nxt[M],go[M],hd[M],dx[M],vis[M],dis[M],jz[M],ans,mi,mx;
void add(int x,int y,int w)
{
nxt[++tot]=hd[x],go[tot]=y,jz[tot]=w,hd[x]=tot;
return ;
}
void build(int x,int l,int r,int lx,int lim)//用lim将第一颗树和第二棵树一起处理
{
if(l==r)
{
x=x+lim;
if(x>mx)mx=x;
dx[++cnt]=x;
return ;
}
int mid=(l+r)>>1;
if(lx==1)add(x+lim,x*2+lim,0),add(x+lim,x*2+1+lim,0);
if(lx==2)add(x*2+lim,x+lim,0),add(x*2+1+lim,x+lim,0);
build(x*2,l,mid,lx,lim);
build(x*2+1,mid+1,r,lx,lim);
}
void search(int x,int l,int r,int lt,int rt,int v,int w,int lx)
{
if(lt<=l&&rt>=r)
{
if(lx==1)add(v,x,w);
else add(x+root-1,v,w);
return ;
}
int mid=(l+r)>>1;
if(lt<=mid)search(x*2,l,mid,lt,rt,v,w,lx);
if(rt>mid)search(x*2+1,mid+1,r,lt,rt,v,w,lx);
return ;
}
struct node
{
int id,zhi;
bool operator<(const node& a)const {return zhi>a.zhi;}
node(int x,int y){id=x,zhi=y;}
};
void dij(int x)
{
memset(dis,0x7f,sizeof(dis));
priority_queue<node> q;
dis[x]=0;
q.push(node(x,0));
while(!q.empty())
{
int u=q.top().id;q.pop();
if(vis[u])continue;
vis[u]=1;
for(int i=hd[u];i;i=nxt[i])
{
int v=go[i];
if(dis[v]>dis[u]+jz[i])
{
dis[v]=dis[u]+jz[i];
if(!vis[v])q.push(node(v,dis[v]));
}
}
}
return ;
}
signed main()
{
scanf("%lld%lld%lld",&n,&q,&s);
build(1,1,n,1,0);
root=mx+1;//第二颗树的root
build(1,1,n,2,mx);//从第二棵树的点表示为mx+1,mx+2,mx+3而不是mx,2*mx,2*mx+1节约空间不然会MLE。
mx=0,mi=1e9;
for(int i=1;i*2<=cnt;i++)//dx存叶子,考虑线段树过程以及两颗线段树相同,可以得出第i(i<=cnt/2)或i-cnt/2(i>cnt/2)个的对应线段树节点为i,
{
if(dx[i]>mx)mx=dx[i];
if(dx[i]<mi)mi=dx[i];
add(dx[i],dx[i+cnt/2],0);
add(dx[i+cnt/2],dx[i],0);//黄色边,即自己向自己连边
}
for(int i=1;i<=q;i++)
{
int lx,l,r,v,w;;scanf("%lld",&lx);
if(lx==1)
{
scanf("%lld%lld%lld",&v,&l,&w);r=l;
search(1,1,n,l,r,dx[v+cnt/2],w,1);
}
if(lx==2)
{
scanf("%lld%lld%lld%lld",&v,&l,&r,&w);
search(1,1,n,l,r,dx[v+cnt/2],w,1);
}
if(lx==3)
{
scanf("%lld%lld%lld%lld",&v,&l,&r,&w);
search(1,1,n,l,r,dx[v],w,2);
}
}
dij(dx[s]);//最短路
for(int i=1;i<=n;i++)
{
if(dis[dx[i]]==9187201950435737471) dis[dx[i]]=-1;//特殊处理不连通
printf("%lld ",dis[dx[i]]);dis存的是线段树节点
}
return 0;
}
别人的建图
void build(int p,int l,int r){
if(l==r){a[l]=p;return ;}
int mid=(l+r)/2;
add(p,p<<1,0),add(p,p<<1|1,0);
add((p<<1)+K,p+K,0),add((p<<1|1)+K,p+K,0);
build(p<<1,l,mid);
build(p<<1|1,mid+1,r);
}
提前计算第一颗树的最大值,计为K.
对于i存i的对应线段树节点。
其他差别不大
Legacy (线段树优化建图)的更多相关文章
- CF786B Legacy 线段树优化建图 + spfa
CodeForces 786B Rick和他的同事们做出了一种新的带放射性的婴儿食品(???根据图片和原文的确如此...),与此同时很多坏人正追赶着他们.因此Rick想在坏人们捉到他之前把他的遗产留给 ...
- Codeforces.786B.Legacy(线段树优化建图 最短路Dijkstra)
题目链接 \(Description\) 有\(n\)个点.你有\(Q\)种项目可以选择(边都是有向边,每次给定\(t,u,v/lr,w\)): t==1,建一条\(u\to v\)的边,花费\(w\ ...
- G. 神圣的 F2 连接着我们 线段树优化建图+最短路
这个题目和之前写的一个线段树优化建图是一样的. B - Legacy CodeForces - 787D 线段树优化建图+dij最短路 基本套路 之前这个题目可以相当于一个模板,直接套用就可以了. 不 ...
- BZOJ5017 [SNOI2017]炸弹 - 线段树优化建图+Tarjan
Solution 一个点向一个区间内的所有点连边, 可以用线段树优化建图来优化 : 前置技能传送门 然后就得到一个有向图, 一个联通块内的炸弹可以互相引爆, 所以进行缩点变成$DAG$ 然后拓扑排序. ...
- 【BZOJ3681】Arietta 树链剖分+可持久化线段树优化建图+网络流
[BZOJ3681]Arietta Description Arietta 的命运与她的妹妹不同,在她的妹妹已经走进学院的时候,她仍然留在山村中.但是她从未停止过和恋人 Velding 的书信往来.一 ...
- 【ARC069F】Flags 2-sat+线段树优化建图+二分
Description 数轴上有 n 个旗子,第 ii 个可以插在坐标 xi或者 yi,最大化两两旗子之间的最小距离. Input 第一行一个整数 N. 接下来 N 行每行两个整数 xi, ...
- 【bzoj5017】[Snoi2017]炸弹 线段树优化建图+Tarjan+拓扑排序
题目描述 在一条直线上有 N 个炸弹,每个炸弹的坐标是 Xi,爆炸半径是 Ri,当一个炸弹爆炸时,如果另一个炸弹所在位置 Xj 满足: Xi−Ri≤Xj≤Xi+Ri,那么,该炸弹也会被引爆. 现在 ...
- 【bzoj4699】树上的最短路(树剖+线段树优化建图)
题意 给你一棵 $n$ 个点 $n-1$ 条边的树,每条边有一个通过时间.此外有 $m$ 个传送条件 $(x_1,y_1,x_2,y_2,c)$,表示从 $x_1$ 到 $x_2$ 的简单路径上的点可 ...
- 【BZOJ4276】[ONTAK2015]Bajtman i Okrągły Robin 线段树优化建图+费用流
[BZOJ4276][ONTAK2015]Bajtman i Okrągły Robin Description 有n个强盗,其中第i个强盗会在[a[i],a[i]+1],[a[i]+1,a[i]+2 ...
- 【bzoj3073】[Pa2011]Journeys 线段树优化建图+堆优化Dijkstra
题目描述 Seter建造了一个很大的星球,他准备建造N个国家和无数双向道路.N个国家很快建造好了,用1..N编号,但是他发现道路实在太多了,他要一条条建简直是不可能的!于是他以如下方式建造道路:(a, ...
随机推荐
- 【转载】只有.dbf数据文件进行数据库恢复
此篇文章为转载,来自 " ITPUB博客 " ,链接:http://blog.itpub.net/26015009/viewspace-714742/ 个人mark下,在之后dbf ...
- 第三章-常用的渗透测试工具-(sqlmap)
常用渗透测试工具 1.sqlmap 支持的数据库:MySQL.Oracle.PostgreSQL.SQL Server.Access.IBM DB2.SQLite.Firebird.Sybase.SA ...
- MacOS安装gprMax教程
原文发布于:https://blog.zhaoxuan.site/archives/19.html: 第一时间获取最新文章请关注博客个人站:https://blog.zhaoxuan.site. 1. ...
- LVS负载均衡(7)-- LVS+keepalived实现高可用
目录 1. LVS+keepalived实现高可用 1.1 实验环境说明 1.2 路由器配置 1.3 WEB服务器nginx配置 1.4 LVS+keepalived配置 1.4.1 keepaliv ...
- C#.Net筑基-运算符🔣Family
C#运算符 内置了丰富的运算符操作类型,使用方便,极大的简化了编码,同时还支持多种运算符重载机制,让自定义的类型也能支持运算符行为. 01.运算符概览 运算符分类 描述 数学运算 基础的加减乘除,及+ ...
- IPv6 — 实践
目录 文章目录 目录 前文列表 常用命令 开启/关闭 IPv6 支持 在 CentOS7 上配置 IPv6 地址 自动获取链路本地地址 配置静态全球唯一地址 配置临时 IPv6 地址 添加 IPv6 ...
- 比Selenium更优秀的playwright介绍与未来展望
Playwright是微软开发的,专门为满足端到端测试需求而创建的.Playwright支持包括Chromium.WebKit和Firefox在内的所有现代渲染引擎.在Windows.Linux和ma ...
- vulnhub --> Web Machine: (N7)
靶场下载地址 Web Machine: (N7) << 点我 开始打靶 ip发现: nmap扫描网段发现靶机ip:192.168.56.101 端口发现: 对靶机进行常规端口扫描 访问网站 ...
- pod(三):pod的管理
目录 一.系统环境 二.前言 三.pod的管理 3.1 环境介绍 3.2 管理pod 一.系统环境 服务器版本 docker软件版本 CPU架构 CentOS Linux release 7.4.17 ...
- linux下date命令设置时间的输出格式和修改时间
目录 一.关于linux下的时间 二.linux下使用date命令设置时间的输出格式 三.修改linux时间 3.1 在可以访问Internet情况下修改时间 3.2 在无法访问Internet情况下 ...