「ZJOI2016」旅行者

对网格图进行分治。

每次从中间选一列,然后枚举每个这一列的格子作为起点跑最短路,进入子矩形时把询问划分一下,有点类似整体二分

至于复杂度么,我不会阿


Code:

#include <cstdio>
#include <cctype>
#include <cstring>
#include <queue>
#include <vector>
#include <algorithm>
using std::min;
template <class T>
void read(T &x)
{
x=0;char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)) x=x*10+c-'0',c=getchar();
}
const int N=1e5+10;
const int inf=0x3f3f3f3f;
std::vector<int> Index[N],R[N],C[N];
int n,m,q,ans[N];
struct koito_yuu
{
int a,b,c,d,id;
}yuu[N],yuul[N],yuur[N];
struct node
{
int v,w;
node(){}
node(int V,int W){v=V,w=W;}
bool friend operator <(node a,node b){return a.w>b.w;}
};
int head[N],to[N<<1],Next[N<<1],edge[N<<1],cnt;
void add(int u,int v,int w)
{
to[++cnt]=v,edge[cnt]=w,Next[cnt]=head[u],head[u]=cnt;
}
int dis[N],vis[N];
void Dijk(int s)
{
std::priority_queue <node> q;
dis[s]=0;
q.push(node(s,0));
while(!q.empty())
{
int now=q.top().v;
q.pop();
if(vis[now]) continue;
vis[now]=1;
for(int v,i=head[now];i;i=Next[i])
if(dis[v=to[i]]>dis[now]+edge[i])
{
dis[v]=dis[now]+edge[i];
q.push(node(v,dis[v]));
}
}
}
bool ckin(int x,int l,int r)
{
return l<=x&&x<=r;
}
bool checkin(koito_yuu yuri,int a,int b,int c,int d)
{
return ckin(yuri.a,a,c)&&ckin(yuri.c,a,c)&&ckin(yuri.b,b,d)&&ckin(yuri.d,b,d);
}
void Divide(int l,int r,int a,int b,int c,int d)
{
if(l>r||a>c||b>d) return;
if(a==c&&b==d)
{
for(int i=l;i<=r;i++) ans[yuu[i].id]=0;
return;
}
int tot=0;
for(int i=a;i<=c;i++)
for(int j=b;j<=d;j++)
Index[i][j]=++tot;
for(int i=1;i<=tot;i++) head[i]=0;
cnt=0;
for(int i=a;i<=c;i++)
for(int j=b;j<d;j++)
{
int u=Index[i][j],v=Index[i][j+1];
add(u,v,R[i][j]),add(v,u,R[i][j]);
}
for(int i=a;i<c;i++)
for(int j=b;j<=d;j++)
{
int u=Index[i][j],v=Index[i+1][j];
add(u,v,C[j][i]),add(v,u,C[j][i]);
}
int lp=0,rp=0,mp=0;
if(c-a>d-b)//横着切
{
int e=a+(c-a>>1);
for(int i=l;i<=r;i++)
{
if(checkin(yuu[i],a,b,e-1,d)) yuul[++lp]=yuu[i];
else if(checkin(yuu[i],e+1,b,c,d)) yuur[++rp]=yuu[i];
}
for(int i=b;i<=d;i++)
{
for(int j=1;j<=tot;j++) dis[j]=inf,vis[j]=0;
Dijk(Index[e][i]);
for(int j=l;j<=r;j++)
{
int id=yuu[j].id,u=Index[yuu[j].a][yuu[j].b],v=Index[yuu[j].c][yuu[j].d];
ans[id]=min(ans[id],dis[u]+dis[v]);
}
}
for(int i=1;i<=lp;i++) yuu[i+l-1]=yuul[i];
for(int i=1;i<=rp;i++) yuu[r-rp+i]=yuur[i];
Divide(l,l+lp-1,a,b,e-1,d),Divide(r-rp+1,r,e+1,b,c,d);
}
else
{
int e=b+(d-b>>1);
for(int i=l;i<=r;i++)
{
if(checkin(yuu[i],a,b,c,e-1)) yuul[++lp]=yuu[i];
else if(checkin(yuu[i],a,e+1,c,d)) yuur[++rp]=yuu[i];
}
for(int i=a;i<=c;i++)
{
for(int j=1;j<=tot;j++) dis[j]=inf,vis[j]=0;
Dijk(Index[i][e]);
for(int j=l;j<=r;j++)
{
int id=yuu[j].id,u=Index[yuu[j].a][yuu[j].b],v=Index[yuu[j].c][yuu[j].d];
ans[id]=min(ans[id],dis[u]+dis[v]);
}
}
for(int i=1;i<=lp;i++) yuu[i+l-1]=yuul[i];
for(int i=1;i<=rp;i++) yuu[r-rp+i]=yuur[i];
Divide(l,l+lp-1,a,b,c,e-1),Divide(r-rp+1,r,a,e+1,c,d);
}
}
int main()
{
memset(ans,0x3f,sizeof ans);
read(n),read(m);
for(int w,i=1;i<=n;i++)
{
R[i].push_back(0);
Index[i].push_back(0);
Index[i].push_back(0);
for(int j=1;j<m;j++)
{
read(w);
R[i].push_back(w);
Index[i].push_back(0);
}
}
for(int i=1;i<=m;i++) C[i].push_back(0);
for(int w,i=1;i<n;i++)
for(int j=1;j<=m;j++)
{
read(w);
C[j].push_back(w);
}
read(q);
for(int i=1;i<=q;i++)
{
read(yuu[i].a),read(yuu[i].b);
read(yuu[i].c),read(yuu[i].d);
yuu[i].id=i;
}
Divide(1,q,1,1,n,m);
for(int i=1;i<=q;i++) printf("%d\n",ans[i]);
return 0;
}

2019.3.11

「ZJOI2016」旅行者 解题报告的更多相关文章

  1. 2090. 「ZJOI2016」旅行者 分治,最短路

    2090. 「ZJOI2016」旅行者 链接 loj 思路 \((l,mid)(mid+1,r)\).考虑跨过mid的贡献. 假设选的中间那条线的点为gzy,贡献为\(dis(x,gzy)+dis(g ...

  2. 「HNOI2016」树 解题报告

    「HNOI2016」树 事毒瘤题... 我一开始以为每次把大树的子树再接给大树,然后死活不知道咋做,心想怕不是个神仙题哦 然后看题解后才发现是把模板树的子树给大树,虽然思维上难度没啥了,但是还是很难写 ...

  3. 「HNOI2016」序列 解题报告

    「HNOI2016」序列 有一些高妙的做法,懒得看 考虑莫队,考虑莫队咋移动区间 然后你在区间内部找一个最小值的位置,假设现在从右边加 最小值左边区间显然可以\(O(1)\),最小值右边的区间是断掉的 ...

  4. 「HNOI2016」网络 解题报告

    「HNOI2016」网络 我有一个绝妙的可持久化树套树思路,可惜的是,它的空间是\(n\log^2 n\)的... 注意到对一个询问,我们可以二分答案 然后统计经过这个点大于当前答案的路径条数,如果这 ...

  5. 「HAOI2018」染色 解题报告

    「HAOI2018」染色 是个套路题.. 考虑容斥 则恰好为\(k\)个颜色恰好为\(c\)次的贡献为 \[ \binom{m}{k}\sum_{i\ge k}(-1)^{i-k}\binom{m-k ...

  6. 「HNOI2016」最小公倍数 解题报告

    「HNOI2016」最小公倍数 考虑暴力,对每个询问,处理出\(\le a,\le b\)的与询问点在一起的联通块,然后判断是否是一个联通块,且联通块\(a,b\)最大值是否满足要求. 然后很显然需要 ...

  7. 「SCOI2016」围棋 解题报告

    「SCOI2016」围棋 打CF后困不拉基的,搞了一上午... 考虑直接状压棋子,然后发现会t 考虑我们需要上一行的状态本质上是某个位置为末尾是否可以匹配第一行的串 于是状态可以\(2^m\)压住了, ...

  8. 「SCOI2016」妖怪 解题报告

    「SCOI2016」妖怪 玄妙...盲猜一个结论,然后过了,事后一证,然后假了,数据真水 首先要最小化 \[ \max_{i=1}^n (1+k)x_i+(1+\frac{1}{k})y_i \] \ ...

  9. 「SCOI2016」美味 解题报告

    「SCOI2016」美味 状态极差无比,一个锤子题目而已 考虑每次对\(b\)和\(d\)求\(c=d \ xor \ (a+b)\)的最大值,因为异或每一位是独立的,所以我们可以尝试按位贪心. 如果 ...

随机推荐

  1. centos 6.9:device eth0 does not seem to be present

    VMware上安装centos6.9,克隆一个新虚机,网卡不能桥接获得宿主机网络地址. https://blog.csdn.net/xiaobei4929/article/details/405152 ...

  2. nginx之快速查找配置文件

    nginx的配置放在nginx.conf文件中,一般我们可以使用以下命令查看服务器中存在的nginx.conf文件.   locate nginx.conf /usr/local/nginx/conf ...

  3. Oracle 创建外部表

    Oracle 外部表能迅速的将海量的数据导入到数据库里面,外部表的创建使用步骤如下: 1 创建一个Directory:必须用sys用户创建,用户存放外部数据文件. create directory D ...

  4. laravel 项目表单中有csrf_token,但一直报错419错误 解决redis连接错误:MISCONF Redis is configured to save RDB snapshots, but it is currently not able to persi

    laravel 项目表单中有csrf_token,但一直报错419错误,因为项目中使用到Redis缓存,在强制关闭Redis后出现的问题,查询laravel.log文件查找相关问题 安装redis后在 ...

  5. C# Note32: 查漏补缺

    (1)Using的三种使用方式 (2)C#详解值类型和引用类型区别 (3)c#中字段(field)和属性(property)的区别 (4)C#中的 int? int?:表示可空类型,就是一种特殊的值类 ...

  6. Python Note1: Pycharm的安装与使用

    前言 曾经学过一段时间python,虽然现在工作了主要使用C#和C++,但是觉得还是有必要在业余的时候学习学习python,提升下自己的知识面,毕竟技多不压身,加油吧! 安装与激活Pycharm 个人 ...

  7. MongoDB操作(1)—MongoDB java驱动核心层次结构及操作流程

    MongoDB之java驱动学习 预备: 本地运行MongoDB采用默认端口20717: 安装MongoDB驱动: 以下关键步骤. 核心层次结构或步骤: 创建连接池:MongoClient实例. 对于 ...

  8. hive安装详解

    1.安装MYSQL simon@simon-Lenovo-G400:~$ sudo apt-get install mysql-server simon@simon-Lenovo-G400:~$ su ...

  9. Java Json 数据下划线与驼峰格式进行相互转换

    概述 今天遇见一个需求,需要对json数据进行下划线与驼峰格式之间进行转换,在Fastjson.Jackson.Gson都提供了转换的方式,在这里进行一下列举. User类: public class ...

  10. laravel 守护进程Supervisor的配置

    安装Supervisor Supervisor是Linux系统中常用的进程守护程序.如果队列进程queue:work意外关闭,它会自动重启启动队列进程.在Ubuntu安装Supervisor 非常简单 ...