分治+最短路,很套路的

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;
int n, m, ans[100005], px[20005], py[20005], uu, hea[20005], cnt, q, din;
int dis[20005];
bool vis[20005];
struct Edge{
int too, nxt, val;
}edge[1000005];
struct Ques{
int xu, yu, xv, yv, id;
}qu[100005], qq[100005];
struct Node{
int idx, dis;
}nd[5000005];
int f(int x, int y){
return (x-1)*m+y;
}
void add_edge(int fro, int too, int val){
edge[++cnt].nxt = hea[fro];
edge[cnt].too = too;
edge[cnt].val = val;
hea[fro] = cnt;
}
bool inn(int x, int nl, int nr, int ml, int mr){
if(px[x]>=nl && px[x]<=nr && py[x]>=ml && py[x]<=mr)
return true;
return false;
}
bool cmp(Node x, Node y){
return x.dis>y.dis;
}
void dijkstra(int x, int nl, int nr, int ml, int mr){
for(int i=nl; i<=nr; i++)
for(int j=ml; j<=mr; j++){
dis[f(i,j)] = 0x3f3f3f3f;
vis[f(i,j)] = false;
}
dis[x] = 0;
din = 1;
nd[1] = (Node){x, 0};
while(din){
int o=nd[1].idx;
pop_heap(nd+1, nd+1+din, cmp);
din--;
if(vis[o]) continue;
vis[o] = true;
for(int i=hea[o]; i; i=edge[i].nxt){
int t=edge[i].too;
if(inn(t, nl, nr, ml, mr) && dis[t]>dis[o]+edge[i].val){
dis[t] = dis[o] + edge[i].val;
nd[++din] = (Node){t, dis[t]};
push_heap(nd+1, nd+1+din, cmp);
}
}
}
}
void solve(int nl, int nr, int ml, int mr, int ql, int qr){
if(ql>qr) return ;
if(nr-nl>mr-ml){
int mid=(nl+nr)>>1;
for(int i=ml; i<=mr; i++){
int p=f(mid, i);
dijkstra(p, nl, nr, ml, mr);
for(int j=ql; j<=qr; j++)
ans[qu[j].id] = min(ans[qu[j].id], dis[f(qu[j].xu, qu[j].yu)]+dis[f(qu[j].xv, qu[j].yv)]);
}
int l=ql, r=qr;
for(int i=ql; i<=qr; i++)
if(qu[i].xu<mid && qu[i].xv<mid) qq[l++] = qu[i];
else if(qu[i].xu>mid && qu[i].xv>mid) qq[r--] = qu[i];
for(int i=ql; i<=qr; i++)
qu[i] = qq[i];
solve(nl, mid-1, ml, mr, ql, l-1);
solve(mid+1, nr, ml, mr, r+1, qr);
}
else{
int mid=(ml+mr)>>1;
for(int i=nl; i<=nr; i++){
int p=f(i, mid);
dijkstra(p, nl, nr, ml, mr);
for(int j=ql; j<=qr; j++)
ans[qu[j].id] = min(ans[qu[j].id], dis[f(qu[j].xu, qu[j].yu)]+dis[f(qu[j].xv, qu[j].yv)]);
}
int l=ql, r=qr;
for(int i=ql; i<=qr; i++)
if(qu[i].yu<mid && qu[i].yv<mid) qq[l++] = qu[i];
else if(qu[i].yu>mid && qu[i].yv>mid) qq[r--] = qu[i];
for(int i=ql; i<=qr; i++)
qu[i] = qq[i];
solve(nl, nr, ml, mid-1, ql, l-1);
solve(nl, nr, mid+1, mr, r+1, qr);
}
}
int main(){
memset(ans, 0x3f, sizeof(ans));
cin>>n>>m;
for(int i=1; i<=n; i++)
for(int j=1; j<m; j++){
scanf("%d", &uu);
int p=f(i,j), q=f(i,j+1);
add_edge(p, q, uu);
add_edge(q, p, uu);
}
for(int i=1; i<n; i++)
for(int j=1; j<=m; j++){
scanf("%d", &uu);
int p=f(i,j), q=f(i+1,j);
add_edge(p, q, uu);
add_edge(q, p, uu);
}
for(int i=1; i<=n; i++)
for(int j=1; j<=m; j++){
int p=f(i,j);
px[p] = i;
py[p] = j;
}
cin>>q;
for(int i=1; i<=q; i++){
scanf("%d %d %d %d", &qu[i].xu, &qu[i].yu, &qu[i].xv, &qu[i].yv);
qu[i].id = i;
}
solve(1, n, 1, m, 1, q);
for(int i=1; i<=q; i++)
printf("%d\n", ans[i]);
return 0;
}

loj2090 「ZJOI2016」旅行者的更多相关文章

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

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

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

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

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

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

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

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

  5. 「ZJOI2016」解题报告

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

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

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

  7. loj2092 「ZJOI2016」大森林

    ref不是太懂-- #include <algorithm> #include <iostream> #include <cstring> #include < ...

  8. loj2091 「ZJOI2016」小星星

    ref 总的来说,就是 容斥转化为点对应到点集问题. 树形 dp 解决转化后的问题. #include <iostream> #include <cstring> #inclu ...

  9. 「ZJOI2016」小星星

    传送门 Description Solution 容斥,考虑有多少个节点不被匹配到,求出的方案,多个点可以同时不被匹配到 状态压缩+树形dp Code  #include<bits/stdc++ ...

随机推荐

  1. base、self标签

    以新的窗口打开页面 self在自己的窗口打开

  2. Vue系列:关于侵权前言

    因为一开始学习 Vue 的时候,秉持的是"好记性不如烂笔头"的思想,所以这些知识点都是当时查阅然后选择性摘录下来的. 当时并没有很刻意去记录原文出处(现在我知错了..),所以..如 ...

  3. 使用create react app教程

    This project was bootstrapped with Create React App. Below you will find some information on how to ...

  4. linux 命令——39 grep (转)

    Linux系统中grep命令是一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹 配的行打印出来.grep全称是Global Regular Expression Print,表示全局正则表达 ...

  5. POJ 3280 Cheapest Palindrome(区间dp)

    dp[i][j]表示处理完i到j的花费,如果s[i] == s[j] 则不需要处理,否则处理s[i]或s[j], 对一个字符ch,加上ch或删掉ch对区间转移来说效果是一样的,两者取min. #inc ...

  6. SSM框架快速搭建

    1.   新建Maven项目 ssm 2.    pom.xml <project xmlns="http://maven.apache.org/POM/4.0.0" xml ...

  7. Java AES加密算法工具类

    AESCodec.java package util; import java.security.Key; import javax.crypto.Cipher; import javax.crypt ...

  8. 漫谈 Clustering (番外篇): Dimensionality Reduction

    由于总是有各种各样的杂事,这个系列的文章竟然一下子拖了好几个月,(实际上其他的日志我也写得比较少),现在决定还是先把这篇降维的日志写完.我甚至都以及忘记了在这个系列中之前有没有讲过“特征”(featu ...

  9. WinSCP使用与linux命令(小部分命令)

    一.下载一个WinSCP WinSCP是一个Windows环境下使用SSH的开源图形化SFTP客户端.同时支持SCP协议.它的主要功能就是在本地与远程计算机间安全的复制文件..winscp也可以链接其 ...

  10. G++ 编译多个源文件

    g++ -c *.cpp g++ graph.o maxflow.o test.o -o test  // 链接顺序必须写对