【bzoj4070】[Apio2015]雅加达的摩天楼 set+堆优化Dijkstra
题目描述
印尼首都雅加达市有 N 座摩天楼,它们排列成一条直线,我们从左到右依次将它们编号为 0 到 N−1。除了这 N 座摩天楼外,雅加达市没有其他摩天楼。
输入
输入的第一行包含两个整数 N 和 M。
输出
输出一行,表示所需要的最少步数。如果消息永远无法传递到 1 号 doge,输出 −1。
样例输入
5 3
0 2
1 1
4 1
样例输出
5
题解
set+堆优化Dijkstra
题目显然可以转化为最短路模型:每个doge所在点向它能够跳到的点连边,长度为步数,最后0号所在位置到1号所在位置的最短路即为答案。
但是这样边数过大。考虑优化:
如果多个doge的bi和bi%pi相同,即能够跳到的点相同,那么可以直接由离某个点最近的doge向该点连边;然后再在这里面位置相邻的doge间连边。即找到一个点的前驱后继位置,这两个位置(如果存在)向它连边。
这样看似没有什么大的优化,其实复杂度直接下降了1个级别。考虑最坏情况下的边数:步长越小的连边越多,因此需要贪心地选择步长短的。当步长为$i$时$b%i$最多只有$i$个,每个连的边是$\frac ni$级别的;而总的个数为$m$,所以只能选择$1~\sqrt m$的步长,因此总的边数时$n\sqrt m$。
最后跑堆优化Dijkstra即可。
时间复杂度$O(n\sqrt n\log n)$
#include <set>
#include <queue>
#include <cstdio>
#include <cstring>
#include <utility>
#include <algorithm>
#define N 30010
using namespace std;
typedef pair<int , int> pr;
struct data
{
int b , p , v;
bool operator<(const data &a)const {return p == a.p ? v == a.v ? b < a.b : v < a.v : p < a.p;}
}a[N];
set<int> ss;
set<int>::iterator it;
priority_queue<pr> q;
int head[N] , to[N * 300] , len[N * 300] , next[N * 300] , cnt , dis[N] , vis[N];
inline void add(int x , int y , int z)
{
to[++cnt] = y , len[cnt] = z , next[cnt] = head[x] , head[x] = cnt;
}
int main()
{
int n , m , i , j , k , s , t , x;
scanf("%d%d" , &n , &m);
for(i = 1 ; i <= m ; i ++ ) scanf("%d%d" , &a[i].b , &a[i].p) , a[i].v = a[i].b % a[i].p;
s = a[1].b , t = a[2].b , sort(a + 1 , a + m + 1);
for(i = j = 1 ; i <= m ; i = j)
{
while(j <= m && a[i].p == a[j].p && a[i].v == a[j].v) j ++ ;
ss.clear();
for(k = i ; k < j ; k ++ ) ss.insert(a[k].b);
for(k = i ; k < j - 1 ; k ++ ) add(a[k].b , a[k + 1].b , (a[k + 1].b - a[k].b) / a[i].p) , add(a[k + 1].b , a[k].b , (a[k + 1].b - a[k].b) / a[i].p);
for(k = a[i].v ; k < n ; k += a[i].p)
{
it = ss.upper_bound(k);
if(it != ss.end()) add(*it , k , (*it - k) / a[i].p);
it = ss.lower_bound(k);
if(it != ss.begin()) it -- , add(*it , k , (k - *it) / a[i].p);
}
}
memset(dis , 0x3f , sizeof(dis)) , dis[s] = 0 , q.push(pr(0 , s));
while(!q.empty())
{
x = q.top().second , q.pop();
if(vis[x]) continue;
vis[x] = 1;
for(i = head[x] ; i ; i = next[i])
if(dis[to[i]] > dis[x] + len[i])
dis[to[i]] = dis[x] + len[i] , q.push(pr(-dis[to[i]] , to[i]));
}
printf("%d\n" , dis[t] == 0x3f3f3f3f ? -1 : dis[t]);
return 0;
}
【bzoj4070】[Apio2015]雅加达的摩天楼 set+堆优化Dijkstra的更多相关文章
- BZOJ4070 [Apio2015]雅加达的摩天楼 【分块 + 最短路】
题目链接 BZOJ4070 题解 考虑暴力建图,将每个\(B_i\)向其能到的点连边,复杂度\(O(\sum \frac{n}{p_i})\),当\(p\)比较小时不适用 考虑优化建图,每个\(dog ...
- 【BZOJ4070】[Apio2015]雅加达的摩天楼 set+最短路
[BZOJ4070][Apio2015]雅加达的摩天楼 Description 印尼首都雅加达市有 N 座摩天楼,它们排列成一条直线,我们从左到右依次将它们编号为 0 到 N−1.除了这 N 座摩天楼 ...
- BZOJ 4070:[APIO2015]雅加达的摩天楼 最短路
4070: [Apio2015]雅加达的摩天楼 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 464 Solved: 164[Submit][Sta ...
- 【题解】P3645 [APIO2015]雅加达的摩天楼(分层图最短路)
[题解]P3645 [APIO2015]雅加达的摩天楼(分层图最短路) 感觉分层图是个很灵活的东西 直接连边的话,边数是\(O(n^2)\)的过不去 然而我们有一个优化的办法,可以建一个新图\(G=( ...
- bzoj 4070 [Apio2015]雅加达的摩天楼 Dijkstra+建图
[Apio2015]雅加达的摩天楼 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 644 Solved: 238[Submit][Status][D ...
- BZOJ 3040 最短路 (堆优化dijkstra)
这题不是裸的最短路么?但是一看数据范围就傻了.点数10^6,边数10^7.这个spfa就别想了(本来spfa就是相当不靠谱的玩意),看来是要用堆优化dijkstra了.但是,平时写dijkstra时为 ...
- UVA - 11374 - Airport Express(堆优化Dijkstra)
Problem UVA - 11374 - Airport Express Time Limit: 1000 mSec Problem Description In a small city c ...
- BZOJ5415[Noi2018]归程——kruskal重构树+倍增+堆优化dijkstra
题目描述 本题的故事发生在魔力之都,在这里我们将为你介绍一些必要的设定. 魔力之都可以抽象成一个 n 个节点.m 条边的无向连通图(节点的编号从 1 至 n).我们依次用 l,a 描述一条边的长度.海 ...
- 配对堆优化Dijkstra算法小记
关于配对堆的一些小姿势: 1.配对堆是一颗多叉树. 2.包含优先队列的所有功能,可用于优化Dijkstra算法. 3.属于可并堆,因此对于集合合并维护最值的问题很实用. 4.速度快于一般的堆结构(左偏 ...
随机推荐
- oracle约束约束状态和设计习惯
oracle约束状态有几个项目,会让人迷惑,分别是: enable/disable--是否启用/禁用 validate/invalidate--确认/不确认 deferrable/not deferr ...
- jQuery 切换图片(图标)效果
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- php 移动或重命名文件(图片)到另一目录下的方法有多种,这里只列出三种:
php 移动或重命名文件(图片)到另一目录下的方法有多种,这里只列出三种: 方法一:使用copy函数 格式:copy(source,destination) 将文件从 source ...
- doT.js使用介绍
doT.js特点是快,小,无依赖其他插件,压缩版仅有4K大小. doT.js详细使用介绍 使用方法: 1 2 3 4 5 6 7 {{ }} 模板 开始标记 结束标记 {{= }} 赋值 {{~ ...
- Python学习:for 循环 与 range()函数
for 循环 For … in 语句是另一种循环语句,其特点是会在一系列对象上进行迭代(Iterates),即它会遍历序列中的每一个项目 注意: 1.else 部分是可选的.当循环中包含它时,它 ...
- Leecode刷题之旅-C语言/python-35.搜索插入位置
/* * @lc app=leetcode.cn id=35 lang=c * * [35] 搜索插入位置 * * https://leetcode-cn.com/problems/search-in ...
- 002---Python基本数据类型--字符串
字符串 .caret, .dropup > .btn > .caret { border-top-color: #000 !important; } .label { border: 1p ...
- Go语言使用百度翻译api
Go语言使用百度翻译api 之前做过一个使用百度翻译api的工具,这个工具用于用户的自动翻译功能,是使用C#调用百度翻译api接口,既然在学习Go语言,那必然也是要使用Go来玩耍一番.这里我是这么安排 ...
- 动态规划----FatMouse’s Speed(HDU 1160)
参考:https://blog.csdn.net/u012655441/article/details/64920825 https://blog.csdn.net/wy19910326/articl ...
- [Jmeter]jmeter数据库性能测试配置
学习jmeter过程中,记录一些学习过程中的点点滴滴,用于备忘.本文主要介绍的是如何创建一个简单的测试计划用户测试数据库服务器. 一.添加线程组 二.添加JDBC请求 1.在第一步里面定义并发用户以及 ...