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++ ...
随机推荐
- vue安装及环境搭建
vue项目在pycharm里运行需要安装一个插件,打开settings,找到plugins,里面搜索vue.js,点击安装. vue安装 先安装node.js npm install -g @vue/ ...
- vuejs 实现富文本
<div v-html="ritchtext" style="font-size:32px;" v-if="!platform" &g ...
- Vue.js(2.x)之列表渲染(v-for/key)
1.v-for是Vue里的循环语句,与其他语言的循环大同小异.首先得有需要循环且不为空的数组,循环的关键字为in或of. 需要索引时的写法: v-for里的in可以使用of代替: 还可以使用v-for ...
- linux打开进程数测试
查看linux默认打开最大打开进程数 具体参考:https://www.jb51.net/article/143667.htm #include <unistd.h> #include & ...
- iphone开发笔记
1.uiimage图片拉伸 - (void)stretchBackgroundImage { //UIImage *originalImage = [[self backgroundImageForS ...
- UVA Live Archive 4015 Cave (树形dp,分组背包)
和Heroes Of Might And Magic 相似,题目的询问是dp的一个副产物. 距离是不好表示成状态的,但是可以换一个角度想,如果知道了从一个点向子树走k个结点的最短距离, 那么就可以回答 ...
- 【洛谷】CYJian的水题大赛 解题报告
点此进入比赛 \(T1\):八百标兵奔北坡 这应该是一道较水的送分题吧. 理论上来说,正解应该是DP.但是,.前缀和优化暴力就能过. 放上我比赛时打的暴力代码吧(\(hl666\)大佬说这种做法的均摊 ...
- 【BZOJ1925】 [SDOI2010] 地精部落(带有一堆性质的动态规划)
点此看题面 大致题意: 问你有多少长度为\(n\)的数列,它当中每个数字要么比旁边两个数字都小,要么比旁边两个数字都大. 性质 这题应该比较显然是一道动态规划题,但刚看到这题时我却无从下手. 其实,了 ...
- 【洛谷2519】[HAOI2011] problem a(动态规划)
点此看题面 大致题意: 一次考试共有\(n\)个人参加,第\(i\)个人说有\(a_i\)个人分数比他高,\(b_i\)个人分数比他低.求最少有几个人说谎. 动态规划 刚看完题目可以说是一头雾水. 仔 ...
- Oracle小知识_长期总结
更新时间:2018年7月16日 11:22:28 一. 系统 1. 打开防火墙后 Oracle 无法链接 新建1521端口规则. 二.知识 A. 序列 1. nextval ------------- ...