loj2090 「ZJOI2016」旅行者
分治+最短路,很套路的
#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」旅行者的更多相关文章
- 「ZJOI2016」旅行者 解题报告
		
「ZJOI2016」旅行者 对网格图进行分治. 每次从中间选一列,然后枚举每个这一列的格子作为起点跑最短路,进入子矩形时把询问划分一下,有点类似整体二分 至于复杂度么,我不会阿 Code: #incl ...
 - 2090. 「ZJOI2016」旅行者 分治,最短路
		
2090. 「ZJOI2016」旅行者 链接 loj 思路 \((l,mid)(mid+1,r)\).考虑跨过mid的贡献. 假设选的中间那条线的点为gzy,贡献为\(dis(x,gzy)+dis(g ...
 - 【LOJ】#2090. 「ZJOI2016」旅行者
		
题解 每次按较长边把矩形分成两半,找一个中间轴,轴上的每个点跑一边最短路更新所有的答案 然后把矩形分成两半,递归下去 代码 #include <bits/stdc++.h> #define ...
 - @loj - 2090@ 「ZJOI2016」旅行者
		
目录 @description@ @solution@ @accepted code@ @details@ @description@ 小 Y 来到了一个新的城市旅行.她发现了这个城市的布局是网格状的 ...
 - 「ZJOI2016」解题报告
		
「ZJOI2016」解题报告 我大浙的省选题真是超级神仙--这套已经算是比较可做的了. 「ZJOI2016」旅行者 神仙分治题. 对于一个矩形,每次我们从最长边切开,最短边不会超过 \(\sqrt{n ...
 - 「ZJOI2016」大森林 解题报告
		
「ZJOI2016」大森林 神仙题... 很显然线段树搞不了 考虑离线操作 我们只搞一颗树,从位置1一直往后移动,然后维护它的形态试试 显然操作0,1都可以拆成差分的形式,就是加入和删除 因为保证了操 ...
 - loj2092 「ZJOI2016」大森林
		
ref不是太懂-- #include <algorithm> #include <iostream> #include <cstring> #include < ...
 - loj2091 「ZJOI2016」小星星
		
ref 总的来说,就是 容斥转化为点对应到点集问题. 树形 dp 解决转化后的问题. #include <iostream> #include <cstring> #inclu ...
 - 「ZJOI2016」小星星
		
传送门 Description Solution 容斥,考虑有多少个节点不被匹配到,求出的方案,多个点可以同时不被匹配到 状态压缩+树形dp Code #include<bits/stdc++ ...
 
随机推荐
- leetcode85 Maximal Rectangle
			
思路: 分别按行拆分后将这一行之前的每列叠加起来,然后使用leetcode84https://www.cnblogs.com/wangyiming/p/9620942.html的思路计算. 实现: # ...
 - 当您在 64 位 Windows 上运行 Regsvr32.exe 时出现错误信息
			
尝试运行 Regsvr32.exe 注册在 64 位版本的 Windows 32 位动态链接库 (DLL) 时您会收到以下错误消息: 若要解决此问题,从 %SystemRoot%\Syswow64 文 ...
 - HDU 1059 Dividing 分配(多重背包,母函数)
			
题意: 两个人共同收藏了一些石头,现在要分道扬镳,得分资产了,石头具有不同的收藏价值,分别为1.2.3.4.5.6共6个价钱.问:是否能公平分配? 输入: 每行为一个测试例子,每行包括6个数字,分别对 ...
 - IOS DatePicker 和 UIBarButtonItem 常用属性
			
- (void)viewDidLoad { [super viewDidLoad]; // // self.inputTextField.inputView = [[UISwitch alloc ] ...
 - MySQL binlog server
			
从5.6版本开始,可以利用 mysqlbinlog命令把远程机器的日志备份到本地目录,这样就更加方便快捷的实现一个binlog server. 环境介绍:192.168.56.100是备份服务器,19 ...
 - vuejs组件
			
<div id='root'> <ul> <todo-item></todo-item> </ul> </div> <sc ...
 - Github的基本功能
			
著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注明出处.作者:Fadeoc Khaos链接:http://www.zhihu.com/question/20070065/answer/30 ...
 - Python-Boolean operation
			
一.布尔运算符 1.x and y: if x is false, then x, else y 2.x or y: if x is false, then y, else x 3.not x: if ...
 - springmvc如何获取参数
			
请参考这篇文章, 写得比较全面. https://www.cnblogs.com/xiaoxi/p/5695783.html
 - jstree前端设置默认选中项
			
$("#jstree").on("loaded.jstree", function (event, data) { var currDeptId = crm.g ...