B - Legacy CodeForces - 787D 线段树优化建图+dij最短路 基本套路
B - Legacy
这个题目开始看过去还是很简单的,就是一个最短路,但是这个最短路的建图没有那么简单,因为直接的普通建图边太多了,肯定会超时的,所以要用线段树来优化建图。
这个题目我一开始也没想到,不知道怎么用线段树优化,然后看了一下题解,豁然开朗。
首先建两棵线段树,有点类似拆点,然后其中一颗从下往上建图A,一颗从上往下建图B。
从上往下建图的每一个叶子节点连着从上往下建图的每一个叶子节点。 权值都是0
p==1 那就直接是B 的叶子节点连着A 的叶子节点,权值为w
p==2 那就是A的叶子节点v 连着B的这个区间的节点
p==3 那就是A 的区间节点连着B的叶子节点v
起点在A这颗树的地球位置的根节点。
建完图之后就是跑一个最短路。
这个是大概思路,但是怎么写呢,
首先肯定是建树,建树的过程中建图,而且还要记录每一个节点的编号,并且记录每一个叶子节点的编号。
然后就是根据要求建图如果是区间就要进行查找这个区间节点就可以了。
接下来就是考验码力的时候了。
这个题目想清楚之后就不是很难写了,只是这个空间要注意,因为这个wa了三发。
这个方法要学习学习。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <vector>
#include <string>
#include <algorithm>
#include <iostream>
#include <map>
#define inf 0x3f3f3f3f
#define inf64 0x3f3f3f3f3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 2e5 + ;
int numa[maxn * ], numb[maxn * ], lefta[maxn * ], leftb[maxn * ];
ll d[maxn*], tot;
int n, m;
bool vis[maxn*];
struct edge {
int from, to, dist;
edge(int from=, int to=, int dist=) :from(from), to(to), dist(dist) {}
};
struct heapnode {
int u;
ll d;
heapnode(ll d=, int u=) : d(d), u(u) {}
bool operator<(const heapnode &a) const {
return a.d < d;
}
}; vector<edge> vec;
vector<int> g[maxn*]; void add(int u,int v,int w)
{
vec.push_back(edge(u, v, w));
int m = vec.size();
g[u].push_back(m - );
// printf("u=%d v=%d w=%d\n", u, v, w);
} void dijkstra(int s) {
priority_queue<heapnode>que;
for (int i = ; i <= tot; i++) d[i] = inf64;
d[s] = ;
memset(vis, , sizeof(vis));
que.push(heapnode(, s));
while (!que.empty()) {
heapnode x = que.top(); que.pop();
int u = x.u;
if (vis[u]) continue;
vis[u] = ;
for (int i = ; i < g[u].size(); i++) {
edge &e = vec[g[u][i]];
// printf("u=%d e.to=%d e.dist=%d\n", u, e.to, e.dist);
// printf("d[%d]=%lld d[%d]=%lld\n", u, d[u], e.to, d[e.to]);
if (d[e.to] > d[u] + e.dist) {
// printf("ww\n");
d[e.to] = d[u] + e.dist;
que.push(heapnode(d[e.to], e.to));
}
}
}
for(int i=;i<=n;i++)
{
if (d[lefta[i]] >= inf64) printf("-1 ");
else printf("%lld ", d[lefta[i]]);
}
} void builda(int id,int l,int r)
{
numa[id] = ++tot;
int mid = (l + r) >> ;
if(l==r)
{
lefta[l] = tot;
return;
}
builda(id << , l, mid);
builda(id << | , mid + , r);
add(numa[id << ], numa[id], );
add(numa[id << | ], numa[id], );
} void buildb(int id,int l,int r)
{
numb[id] = ++tot;
int mid = (l + r) >> ;
if(l==r)
{
leftb[l] = tot;
return;
}
buildb(id << , l, mid);
buildb(id << | , mid + , r);
add(numb[id], numb[id << ], );
add(numb[id], numb[id << | ], );
} void build3(int n)
{
for (int i = ; i <= n; i++) add(leftb[i], lefta[i], );
} void updatea(int id,int l,int r,int x,int y,int b,int w)
{
if (x <= l && y >= r) {
add(numa[id], b, w);
return;
}
int mid = (l + r) >> ;
if (x <= mid) updatea(id << , l, mid, x, y, b, w);
if (y > mid) updatea(id << | , mid + , r, x, y, b, w);
} void updateb(int id,int l,int r,int x,int y,int a,int w)
{
if(x<=l&&y>=r)
{
add(a, numb[id], w);
return;
}
int mid = (l + r) >> ;
if (x <= mid) updateb(id << , l, mid, x, y, a, w);
if (y > mid) updateb(id << | , mid + , r, x, y, a, w);
} int main()
{
int s;
tot = ;
scanf("%d%d%d", &n, &m, &s);
builda(, , n), buildb(, , n), build3(n);
while(m--)
{
int opt, u, v, l, r, w;
scanf("%d", &opt);
if (opt == ) {
scanf("%d%d%d", &u, &v, &w);
add(lefta[u], leftb[v], w);
}
if(opt==)
{
scanf("%d%d%d%d", &u, &l, &r, &w);
updateb(, , n, l, r, lefta[u], w);
}
if(opt==)
{
scanf("%d%d%d%d", &u, &l, &r, &w);
updatea(, , n, l, r, leftb[u], w);
}
}
dijkstra(lefta[s]);
return ;
}
线段树+最短路
B - Legacy CodeForces - 787D 线段树优化建图+dij最短路 基本套路的更多相关文章
- G. 神圣的 F2 连接着我们 线段树优化建图+最短路
这个题目和之前写的一个线段树优化建图是一样的. B - Legacy CodeForces - 787D 线段树优化建图+dij最短路 基本套路 之前这个题目可以相当于一个模板,直接套用就可以了. 不 ...
- CF786B Legacy 线段树优化建图 + spfa
CodeForces 786B Rick和他的同事们做出了一种新的带放射性的婴儿食品(???根据图片和原文的确如此...),与此同时很多坏人正追赶着他们.因此Rick想在坏人们捉到他之前把他的遗产留给 ...
- [Codeforces 1197E]Culture Code(线段树优化建图+DAG上最短路)
[Codeforces 1197E]Culture Code(线段树优化建图+DAG上最短路) 题面 有n个空心物品,每个物品有外部体积\(out_i\)和内部体积\(in_i\),如果\(in_i& ...
- 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 ...
随机推荐
- 《带你装B,带你飞》pytest修仙之路5 - yield操作
1. 简介 上一篇中,我们刚刚实现了在每个用例之前执行初始化操作,那么用例执行完之后如需要清除数据(或还原)操作,可以使用 yield 来实现.fixture通过scope参数控制setup级别,既然 ...
- 小说光看还不够?用Python做有声小说!
文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. PS:如有需要Python学习资料的小伙伴可以加点击下方链接自行获取http:// ...
- 基于canvas的画板
最近重新在看Html5&CSS3的知识,看到canvas的时候,想到了以前在学校学计算机图形学时做过的画图实验,于是想,可以基于html5和css3来做一款画板,经过1天的努力,完成了画板的一 ...
- 利用 PhpQuery 随机爬取妹子图
前言 运行下面的代码会随机得到妹子图的一张图片,代码中的phpQuery可以在这里下载:phpQuery-0.9.5.386.zip <?php require 'phpQuery.php'; ...
- Redis分布式锁的正确姿势
1. 核心代码: import redis.clients.jedis.Jedis; import java.util.Collections; /** * @Author: qijigui * @C ...
- Win7+Linux双系统,完美解决删除Linux后出现的任何问题!
首先,进入到Win7,安装MiniTool Partition Wizard Home Edition删除掉Linux分区, 点Yes 然后选中 这里选中这个,重写MBR,开机神马grub神马问题都没 ...
- 一种特殊的生成器函数-Generator函数
本节的内容,是建立在iterator遍历器知识的基础上.所以希望还没有看上一节的内容的话,最好还是看一看,当然你如果熟悉iterator就没有那个必要了. 既然你都看到这里来了,就咱们就接着往下讲.. ...
- PE文件学习(1)DOS和NT
大致结构 DOS头和NT头之间通常还有个DOS Stub DOS头 DOS头的作用是兼容MS-DOS操作系统中的可执行文件 一般没啥用 记录着PE头的位置 DOS头定义部分 typedef struc ...
- centos7下端口映射
firewall-cmd --zone=external --add-forward-port=port=:proto=tcp:toport=:toaddr=192.168.10.10 --perma ...
- MFC之动态调用自己写的类库中的类的成员方法
第一步:创建一个要调用的类库 如果是MFC程序使用,可以创建一个MFC的类库,不过依然可以创建一个win32类库.我所知道的,MFC的类库可以分为常规MFC DLL和MFC扩展DLL关于它们之间的区别 ...