2090. 「ZJOI2016」旅行者

链接

loj

思路

\((l,mid)(mid+1,r)\).考虑跨过mid的贡献。

假设选的中间那条线的点为gzy,贡献为\(dis(x,gzy)+dis(gzy,y)\)

那就计算n遍最短路,一次分治为\(n^2mlog{nm}\)

设S=n*m.矩阵的长度是不定的,每次取最长的边进行分治是最好的,n最坏为\(\sqrt{n}\)。

\(f(n)=2*f(\frac{n}{2})+S\sqrt{S}logS。所以总的复杂度就是\)\(S\sqrt{S}logS\)

都在同侧的也需要跨一跨

代码

  1. #include <bits/stdc++.h>
  2. #define FOR(i,a,b) for(int i=a;i<=b;++i)
  3. using namespace std;
  4. const int _=1e5+7,INF=0x3f3f3f3f;
  5. int read() {
  6. int x=0,f=1;char s=getchar();
  7. for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;
  8. for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
  9. return x*f;
  10. }
  11. int n,m,q,ans[_],vis[_];
  12. struct node {
  13. int x,y,X,Y,u,v,id;
  14. }Q[_],tmp[_];
  15. bool cmp(node a,node b) {return a.id<b.id;}
  16. struct edge {int v,nxt,q;}e[_];
  17. int head[_],tot;
  18. void add(int u,int v,int q) {
  19. e[++tot].v=v;
  20. e[tot].q=q;
  21. e[tot].nxt=head[u];
  22. head[u]=tot;
  23. }
  24. int id(int x,int y) {return (x-1)*m+y;}
  25. struct T_T {
  26. int u,val;
  27. T_T(int a=0,int b=0) {u=a,val=b;}
  28. bool operator < (const T_T &b) const {return val>b.val;}
  29. };
  30. int dis[_];
  31. void dij(int S) {
  32. dis[S]=0;
  33. priority_queue<T_T> q;
  34. q.push(T_T(S,0));
  35. while(!q.empty()) {
  36. T_T u=q.top();q.pop();
  37. if(dis[u.u]!=u.val) continue;
  38. for(int i=head[u.u];i;i=e[i].nxt) {
  39. int v=e[i].v;
  40. if(vis[v]&&dis[v]>u.val+e[i].q) {
  41. dis[v]=u.val+e[i].q;
  42. q.push(T_T(v,dis[v]));
  43. }
  44. }
  45. }
  46. }
  47. void solve(int x,int y,int X,int Y,int l,int r) {
  48. if(l>r) return;
  49. if(x==X&&y==Y) {
  50. for(int i=l;i<=r;++i) ans[Q[i].id]=0;
  51. return;
  52. }
  53. if(Y-y>X-x) {
  54. int mid=(Y+y)>>1;
  55. FOR(i,x,X) {
  56. FOR(j,x,X) FOR(k,y,Y) dis[id(j,k)]=INF;
  57. dij(id(i,mid));
  58. FOR(j,l,r)
  59. ans[Q[j].id]=min(dis[Q[j].u]+dis[Q[j].v],ans[Q[j].id]);
  60. }
  61. FOR(i,x,X) vis[id(i,mid)]=0;
  62. int p=l,q=r;
  63. FOR(i,l,r) {
  64. if(max(Q[i].y,Q[i].Y)<=mid) tmp[p++]=Q[i];
  65. if(min(Q[i].y,Q[i].Y)>mid) tmp[q--]=Q[i];
  66. }
  67. FOR(i,l,r) Q[i]=tmp[i];
  68. solve(x,y,X,mid,l,p-1);
  69. solve(x,mid+1,X,Y,q+1,r);
  70. } else {
  71. int mid=(X+x)>>1;
  72. FOR(i,y,Y) {
  73. FOR(j,x,X) FOR(k,y,Y) dis[id(j,k)]=INF;
  74. dij(id(mid,i));
  75. FOR(j,l,r)
  76. ans[Q[j].id]=min(dis[Q[j].u]+dis[Q[j].v],ans[Q[j].id]);
  77. }
  78. FOR(i,y,Y) vis[id(mid,i)]=0;
  79. int p=l,q=r;
  80. FOR(i,l,r) {
  81. if(max(Q[i].x,Q[i].X)<=mid) tmp[p++]=Q[i];
  82. if(min(Q[i].x,Q[i].X)>mid) tmp[q--]=Q[i];
  83. }
  84. FOR(i,l,r) Q[i]=tmp[i];
  85. solve(x,y,mid,Y,l,p-1);
  86. solve(mid+1,y,X,Y,q+1,r);
  87. }
  88. }
  89. int main() {
  90. n=read(),m=read();
  91. FOR(i,1,n) FOR(j,1,m-1) {
  92. int val=read();
  93. add(id(i,j),id(i,j+1),val);
  94. add(id(i,j+1),id(i,j),val);
  95. }
  96. FOR(i,1,n-1) FOR(j,1,m) {
  97. int val=read();
  98. add(id(i,j),id(i+1,j),val);
  99. add(id(i+1,j),id(i,j),val);
  100. }
  101. FOR(i,1,n) FOR(j,1,m) vis[id(i,j)]=1;
  102. q=read();
  103. FOR(i,1,q) {
  104. Q[i].x=read(),Q[i].y=read(),
  105. Q[i].u=id(Q[i].x,Q[i].y);
  106. Q[i].X=read(),Q[i].Y=read(),
  107. Q[i].v=id(Q[i].X,Q[i].Y);
  108. Q[i].id=i,ans[i]=INF;
  109. }
  110. solve(1,1,n,m,1,q);
  111. FOR(i,1,q) printf("%d\n",ans[i]);
  112. return 0;
  113. }

2090. 「ZJOI2016」旅行者 分治,最短路的更多相关文章

  1. @loj - 2090@ 「ZJOI2016」旅行者

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 小 Y 来到了一个新的城市旅行.她发现了这个城市的布局是网格状的 ...

  2. 【LOJ】#2090. 「ZJOI2016」旅行者

    题解 每次按较长边把矩形分成两半,找一个中间轴,轴上的每个点跑一边最短路更新所有的答案 然后把矩形分成两半,递归下去 代码 #include <bits/stdc++.h> #define ...

  3. 「ZJOI2016」旅行者 解题报告

    「ZJOI2016」旅行者 对网格图进行分治. 每次从中间选一列,然后枚举每个这一列的格子作为起点跑最短路,进入子矩形时把询问划分一下,有点类似整体二分 至于复杂度么,我不会阿 Code: #incl ...

  4. loj2090 「ZJOI2016」旅行者

    分治+最短路,很套路的 #include <algorithm> #include <iostream> #include <cstring> #include & ...

  5. 「ZJOI2016」解题报告

    「ZJOI2016」解题报告 我大浙的省选题真是超级神仙--这套已经算是比较可做的了. 「ZJOI2016」旅行者 神仙分治题. 对于一个矩形,每次我们从最长边切开,最短边不会超过 \(\sqrt{n ...

  6. 「ZJOI2016」大森林 解题报告

    「ZJOI2016」大森林 神仙题... 很显然线段树搞不了 考虑离线操作 我们只搞一颗树,从位置1一直往后移动,然后维护它的形态试试 显然操作0,1都可以拆成差分的形式,就是加入和删除 因为保证了操 ...

  7. 「bzoj1003」「ZJOI2006」物流运输 最短路+区间dp

    「bzoj1003」「ZJOI2006」物流运输---------------------------------------------------------------------------- ...

  8. [BZOJ4456] [Zjoi2016]旅行者 分治+最短路

    4456: [Zjoi2016]旅行者 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 777  Solved: 439[Submit][Status] ...

  9. 【BZOJ4456】[Zjoi2016]旅行者 分治+最短路

    [BZOJ4456][Zjoi2016]旅行者 Description 小Y来到了一个新的城市旅行.她发现了这个城市的布局是网格状的,也就是有n条从东到西的道路和m条从南到北的道路,这些道路两两相交形 ...

随机推荐

  1. 『kamp 树形dp』

    kamp Description jz 市的云台山是个很美丽的景区,小 x 暑期到云台山打工,他的任务是开景区的大巴. 云台山景区有 N 个景点,这 N 个景点由 N-1 条道路连接而成,我们保证这 ...

  2. Java学习:File类

    Java学习:File类 File类的概述 重点:记住这三个单词 绝对路径和相对路径 File类的构造方法 File类判断功能的方法 File类创建删除功能的方法 File类获取(文件夹)目录和文件夹 ...

  3. handle句柄

    若是你向我问起 Win32 程序设计中印象最深(最坑爹)的一个概念是什么,那么我会毫不犹豫地告诉你——句柄(Handles).究其原因,无论是 MSDN 还是 维基百科,对于“句柄”这个词的解说都显得 ...

  4. EF 通过导航添加数据

    Fluent Api是指定模型与数据库表之间的对应关系 //一对多 this.HasOptional(x => x.主表).WithMany(x => x.多表).HasForeignKe ...

  5. tkinter事件键盘绑定

    tkinter事件键盘绑定 from tkinter import * root=Tk() #创建一个框架,在这个框架中响应事件 frame=Frame(root, width=200,height= ...

  6. Object.assign的使用

    语法: Object.assign(target, ...sources)//target目标对象,sources源对象,返回值目标对象 使用说明: 如果目标对象中的属性具有相同的键,则属性将被源对象 ...

  7. em与rem之间的区别以及移动设备中的rem适配方案

    em与rem之间的区别: 共同点: 它们都是像素单位 它们都是相对单位 不同点: em大小是基于父元素的字体大小 rem大小是基于根元素(html)的字体的大小 实例: <!DOCTYPE ht ...

  8. SAP里SE38设置模板

    经验丰富些的大佬们都会有一套自己的风格,比如report主程序里几个form,常见的fieldcat的宏定义,常见的一些数据定义等等. 1.使用事物代码SE38进入编辑器. 2.点击客户端最右下角的文 ...

  9. Linux自有服务(1)-Linux从入门到精通第五天(非原创)

    文章大纲 一.运行模式二.用户与用户组管理(重点)三.网络设置四.ssh服务(重点)五.学习资料下载六.参考文章   自有服务,即不需要用户独立去安装的软件的服务,而是当系统安装好之后就可以直接使用的 ...

  10. 创建readonly只读用户脚本

    身为一名运维工作人员,保证服务器的安全是必要项,当开发人员或测试人员需登录到服务器查看日志等操作时,可只给定特定的权限防止误操作的惨况产生. 以下脚本内容均为我本人环境,如有更改可自行修改. ~]# ...