我们是想跑最短路的

我们有两种建图方式:

1.对于每个doge i,连向B[j]==B[i]+P[i]*k ,k=..,-2,-1,0,1,2,... ,边权=|k|,这样连的复杂度是$O(N\sum\limits_{i=1}^{m}\frac{1}{P[i]})$

2.对于每个楼i,建max(P[i])个点,表示可以有一个doge经过这个楼来跳j个距离,也就是说,给P[i][j]连向P[i-j][j]和P[i+j][j],边权=1,而且还要给所有的P[i]连起来,边权是0.

这样连的复杂度是$O(N\sum\limits_{i=1}^{m}P[i])$,其中P[i]是互不相同的(相同就不加了)

然而都过不了

然后我们发现,复杂度一个是乘P[i],一个是除以P[i],这就启发我们采用分块的思想,对于P[i]大于$\sqrt{N}$的使用第1种建法,小于的使用第二种建法,整体的复杂度就变成$O(N\sqrt{N})$了

然而因为玄学的常数问题,我们需要:

1.让那个分块的边界取$min(\sqrt{N},100)$(我也不知道为什么)

2.在做最短路的时候再计算边,而不是提前都建好

3.深吸一口氧气(必要)

4.使用spfa而不是dijkstra(我也不知道为什么,但我还是用了dijkstra,然后就挂了...)

(代码写一年还写得巨丑)

 1 #include<bits/stdc++.h>
 2 #define pa pair<int,int>
 3 #define lowb(x) ((x)&(-(x)))
 4 #define REP(i,n0,n) for(i=n0;i<=n;i++)
 5 #define PER(i,n0,n) for(i=n;i>=n0;i--)
 6 #define MAX(a,b) ((a>b)?a:b)
 7 #define MIN(a,b) ((a<b)?a:b)
 8 #define CLR(a,x) memset(a,x,sizeof(a))
 9 #define rei register int
10 using namespace std;
11 typedef long long ll;
12 const int maxn=30030,sqrtn=200;
13
14 inline ll rd(){
15     ll x=0;char c=getchar();int neg=1;
16     while(c<'0'||c>'9'){if(c=='-') neg=-1;c=getchar();}
17     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
18     return x*neg;
19 }
20
21 struct Node{
22     int x,y,d;bool isp;
23     Node (int a,int b,int c,bool s){x=a,y=b,d=c,isp=s;}
24 }S=Node(0,0,0,0);
25 int N,SN,M,B[maxn],P[maxn];
26 int dis[maxn*sqrtn],poi[maxn][2],ph[maxn];
27 bool flag[maxn*sqrtn];
28 priority_queue<Node,vector<Node>,greater<Node> > q;
29
30 bool operator > (Node a,Node b){return a.d>b.d;}
31 inline int id(Node a){return a.isp?a.x:M+1+a.x+a.y*N;}
32 inline void print(int x,Node a){printf("Node%d:%d %d %d %d\n",x,a.x,a.y,a.d,a.isp);}
33
34 inline int dijkstra(){
35     memset(dis,127,sizeof(dis));
36     dis[id(S)]=0;q.push(S);
37     while(!q.empty()){
38         Node p=q.top();q.pop();
39         if(((!p.isp)&&p.x==B[1])||(p.isp&&p.x==1)) return p.d;
40         if(flag[id(p)]) continue;
41
42         if(!p.isp){
43             for(int i=ph[p.x];i!=-1;i=poi[i][1]){
44                 if(P[poi[i][0]]>SN){
45                     if(dis[poi[i][0]]<=p.d) continue;
46                     dis[poi[i][0]]=p.d;
47                     q.push(Node(poi[i][0],0,p.d,1));
48                 }else if(P[poi[i][0]]!=p.y){
49                     Node x=Node(p.x,P[poi[i][0]],p.d,0);
50                     if(dis[id(x)]<=p.d) continue;
51                     dis[id(x)]=p.d;q.push(x);
52                 }
53             }
54             if(p.y){
55                 Node xx=Node(p.x+p.y,p.y,p.d+1,0);
56                 if(p.x+p.y<N&&dis[id(xx)]>p.d+1){
57                     dis[id(xx)]=p.d+1;
58                     q.push(xx);
59                 }xx.x=p.x-p.y;
60                 if(p.x-p.y>=0&&dis[id(xx)]>p.d+1){
61                     dis[id(xx)]=p.d+1;
62                     q.push(xx);
63                 }
64             }
65         }
66         else{
67             for(int i=B[p.x]+P[p.x],j=1;i<N;i+=P[p.x],j++){
68                 Node a=Node(i,0,p.d+j,0);
69                 if(dis[id(a)]>p.d+j){
70                     dis[id(a)]=p.d+j;q.push(a);
71                 }
72             }
73             for(int i=B[p.x]-P[p.x],j=1;i>=0;i-=P[p.x],j++){
74                 Node a=Node(i,0,p.d+j,0);
75                 if(dis[id(a)]>p.d+j){
76                     dis[id(a)]=p.d+j;q.push(a);
77                 }
78             }
79         }
80         flag[id(p)]=1;
81     }return -1;
82 }
83
84 int main(){
85     //freopen(".in","r",stdin);
86     rei i,j,k;
87     N=rd(),M=rd();SN=min(100,(int)sqrt(N));
88     memset(ph,-1,sizeof(ph));
89     for(i=0;i<M;i++){
90         B[i]=rd(),P[i]=rd();
91         poi[i][0]=i;poi[i][1]=ph[B[i]];ph[B[i]]=i;
92     }S=Node(B[0],0,0,0);
93     printf("%d\n",dijkstra());
94     return 0;
95 }

转载于:https://www.cnblogs.com/Ressed/p/9649006.html

luogu3645 [Apio2015]雅加达的摩天大楼 (分块+dijkstra)相关推荐

  1. bzoj4070 [Apio2015]雅加达的摩天楼 分块+spfa

    Description 印尼首都雅加达市有 N 座摩天楼,它们排列成一条直线,我们从左到右依次将它们编号为 0 到 N−1.除了这 N 座摩天楼外,雅加达市没有其他摩天楼. 有 M 只叫做 " ...

  2. BZOJ 4070 [Apio2015]雅加达的摩天楼 ——分块 SPFA

    挺有趣的分块的题目. 直接暴力建边SPFA貌似是$O(nm)$的. 然后考虑分块,$\sqrt n$一下用虚拟节点辅助连边, 以上的直接暴力连边即可. 然后卡卡时间,卡卡空间. 终于在UOJ上T掉辣. ...

  3. 4070: [Apio2015]雅加达的摩天楼

    4070: [Apio2015]雅加达的摩天楼 Time Limit: 10 Sec   Memory Limit: 256 MB Submit: 415   Solved: 146 [ Submit ...

  4. 题解 P3645 【[APIO2015]雅加达的摩天楼】

    题解 P3645 [[APIO2015]雅加达的摩天楼] 一看求最短先想dp,发现要考虑的状态和转移太多没法做. 再一看是从一个点往另一个点跳,可以考虑最短路. 直接建边会O(n^2) 优化:本题中, ...

  5. 【BZOJ 4070】 [Apio2015]雅加达的摩天楼

    4070: [Apio2015]雅加达的摩天楼 Time limit: 1000 ms Memory limit: 262144 KB Description The city of Jakarta ...

  6. bzoj 4070: [Apio2015]雅加达的摩天楼 最短路+分块

    题意 印尼首都雅加达市有 N 座摩天楼,它们排列成一条直线,我们从左到右依次将它们编号为 0 到 N−1.除了这 N 座摩天楼外,雅加达市没有其他摩天楼. 有 M 只叫做 "doge&quo ...

  7. 【bzoj4070】[Apio2015]雅加达的摩天楼 set+堆优化Dijkstra

    题目描述 印尼首都雅加达市有 N 座摩天楼,它们排列成一条直线,我们从左到右依次将它们编号为 0 到 N−1.除了这 N 座摩天楼外,雅加达市没有其他摩天楼. 有 M 只叫做 "doge&q ...

  8. 解题:APIO 2015 雅加达的摩天大楼

    题面 分块思想+最短路 发现对于步长小的doge会连出很多边,很容易导致大量的重边,于是对doge们根据步长分块讨论:根据步长建出分层图,然后把步长不超过某个值的doge们连到对应层上的点上,其余的d ...

  9. 洛谷P3645 [APIO2015]雅加达的摩天楼

    题目描述 印尼首都雅加达市有 N 座摩天楼,它们排列成一条直线,我们从左到右依次将它们编号为 0 到 N − 1.除了这 NN 座摩天楼外,雅加达市没有其他摩天楼. 有 M 只叫做 "dog ...

最新文章

  1. 彻底删除SharePoint 2010 Content Database
  2. Python数据库添加时间
  3. U盘文件名称变成乱码的解决方法
  4. 数据库-事务并发操作问题及并发的控制
  5. surfaceView中的线程问题
  6. html计算器_学习HTML、CSS和JavaScript的最佳方法是什么?
  7. 图像相似度(信息学奥赛一本通-T1123)
  8. 复旦微电子fpga数据手册_牛眼IPO | 复旦微闯关科创板:主要产品售价走低、晶圆成本却在上升...
  9. php索引数组转键数组,PHP-Codeigniter:如何从指定索引转换数组值?
  10. ASP.NET Core MVC 源码学习:详解 Action 的激活
  11. 计算机报名登录服务器超时,登录服务器超时
  12. 解析ES6箭头函数中的this
  13. 设计模式:卑微的代理模式
  14. win10java编辑器_5个最好的Windows 10的字幕编辑软件
  15. 单片机问题,24V NPN接近开关信号,怎么接入到单片机
  16. java调用clsid_java – Utgard – 拒绝访问
  17. #力扣 LeetCode1646. 获取生成数组中的最大值 @FDDLC
  18. 仿制网站被抄袭的几个有效解决的方法
  19. 【PC工具】chrome谷歌浏览器各种版本,最好用的浏览器没有之一。低调使用福利...
  20. 网吧服务器掉硬盘,网吧服务器磁盘压力大的解决过程

热门文章

  1. 3-Raven2百个靶机渗透(精写-思路为主)
  2. 『生活』很多BT的事情都发生在今晚.(好像应该是今早)
  3. AutoCAD Civil 3D-部件-石料场开挖边坡部件设计及装配
  4. go语言面向对象 练手小项目
  5. Linux设备检测外部网络NAT类型
  6. AfterCodecs for Mac(AE/PR/ME编码加速输出渲染插件)含序列号
  7. 模拟键盘的终极模拟2
  8. 取整函数(向上取整 向下取整 四舍五入)
  9. 【C/C++】字符串函数之复制函数
  10. 一个普通青年的成长故事