Bzoj4456: [Zjoi2016]旅行者
2018-03-22 13:59
393 查看
题目
传送门Sol
离线+分治+\(djikstra\)每次把网格图分成两部分
如果起点和终点分隔两边,那么它一定会经过中轴线
枚举中轴线上的点跑\(dijkstra\)
然后处理询问,递归处理起点终点在一起的询问
# include <bits/stdc++.h> # define RG register # define IL inline # define Fill(a, b) memset(a, b, sizeof(a)) using namespace std; typedef long long ll; const int _(1e5 + 5); const int INF(1e9); IL int Input(){ RG int x = 0, z = 1; RG char c = getchar(); for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1; for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48); return x * z; } int n, m, q, dis[_], ans[_]; struct Query{ int x1, y1, x2, y2, s, t, id; } qry[_], tmp1[_], tmp2[_]; int vis[_], first[_], cnt; struct Edge{ int to, next, w; } edge[_ << 1]; struct Data{ int u, w; IL bool operator <(RG Data B) const{ return w > B.w; } }; priority_queue <Data> Q; IL void Add(RG int u, RG int v, RG int w){ edge[cnt] = (Edge){v, first[u], w}, first[u] = cnt++; } # define ID(x, y) (x - 1) * m + y IL void Dijkstra(RG int l1, RG int r1, RG int l2, RG int r2, RG int S){ for(RG int i = l1; i <= l2; ++i) for(RG int j = r1; j <= r2; ++j){ RG int id = ID(i, j); dis[id] = INF, vis[id] = 0; } dis[S] = 0, Q.push((Data){S, 0}); while(!Q.empty()){ RG Data s = Q.top(); Q.pop(); if(vis[s.u]) continue; vis[s.u] = 1; for(RG int e = first[s.u]; e != -1; e = edge[e].next){ RG int v = edge[e].to, w = edge[e].w; if(vis[v]) continue; if(dis[s.u] + w < dis[v]){ dis[v] = dis[s.u] + w; Q.push((Data){v, dis[v]}); } } } } IL void Solve(RG int l1, RG int r1, RG int l2, RG int r2, RG int l, RG int r){ if(l1 == l2 && r1 == r2){ for(RG int i = l; i <= r; ++i) ans[qry[i].id] = 0; return; } if(l2 - l1 > r2 - r1){ RG int mid = (l1 + l2) >> 1, cnt1 = 0, cnt2 = 0; for(RG int i = r1; i <= r2; ++i){ RG int p = ID(mid, i); Dijkstra(l1, r1, l2, r2, p); for(RG int j = l; j <= r; ++j) ans[qry[j].id] = min(ans[qry[j].id], dis[qry[j].s] + dis[qry[j].t]); } for(RG int i = l; i <= r; ++i) if(qry[i].x1 <= mid && qry[i].x2 <= mid) tmp1[++cnt1] = qry[i]; else if(qry[i].x1 > mid && qry[i].x2 > mid) tmp2[++cnt2] = qry[i]; for(RG int i = 1; i <= cnt1; ++i) qry[l + i - 1] = tmp1[i]; for(RG int i = 1; i <= cnt2; ++i) qry[cnt1 + l - 1 + i] = tmp2[i]; Solve(l1, r1, mid, r2, l, cnt1 + l - 1), Solve(mid + 1, r1, l2, r2, cnt1 + l, l + cnt2 + cnt1 - 1); } else{ RG int mid = (r1 + r2) >> 1, cnt1 = 0, cnt2 = 0; for(RG int i = l1; i <= l2; ++i){ RG int p = ID(i, mid); Dijkstra(l1, r1, l2, r2, p); for(RG int j = l; j <= r; ++j) ans[qry[j].id] = min(ans[qry[j].id], dis[qry[j].s] + dis[qry[j].t]); } for(RG int i = l; i <= r; ++i) if(qry[i].y1 <= mid && qry[i].y2 <= mid) tmp1[++cnt1] = qry[i]; else if(qry[i].y1 > mid && qry[i].y2 > mid) tmp2[++cnt2] = qry[i]; for(RG int i = 1; i <= cnt1; ++i) qry[l + i - 1] = tmp1[i]; for(RG int i = 1; i <= cnt2; ++i) qry[cnt1 + l - 1 + i] = tmp2[i]; Solve(l1, r1, l2, mid, l, cnt1 + l - 1), Solve(l1, mid + 1, l2, r2, cnt1 + l, l + cnt1 + cnt2 - 1); } } int main(RG int argc, RG char *argv[]){ n = Input(), m = Input(); for(RG int i = 1; i <= n; ++i) for(RG int j = 1; j <= m; ++j){ RG int id = ID(i, j); vis[id] = 1, first[id] = -1; } for(RG int i = 1; i <= n; ++i) for(RG int j = 1; j < m; ++j){ RG int u = ID(i, j), v = ID(i, j + 1), w = Input(); Add(u, v, w), Add(v, u, w); } for(RG int i = 1; i < n; ++i) for(RG int j = 1; j <= m; ++j){ RG int u = ID(i, j), v = ID(i + 1, j), w = Input(); Add(u, v, w), Add(v, u, w); } q = Input(); for(RG int i = 1; i <= q; ++i){ RG int x1 = Input(), y1 = Input(), s = ID(x1, y1), x2 = Input(), y2 = Input(), t = ID(x2, y2); qry[i] = (Query){x1, y1, x2, y2, s, t, i}, ans[i] = INF; } Solve(1, 1, n, m, 1, q); for(RG int i = 1; i <= q; ++i) printf("%d\n", ans[i]); return 0; }
相关文章推荐
- BZOJ4456: [Zjoi2016]旅行者
- bzoj4456: [Zjoi2016]旅行者
- [分治 + 最短路] BZOJ4456: [Zjoi2016]旅行者
- Bzoj4456: [Zjoi2016]旅行者
- 4456: [Zjoi2016]旅行者 分治+最短路
- [分治 最短路] BZOJ 4456 [Zjoi2016]旅行者
- BZOJ4456 [Zjoi2016]旅行者
- ●BOZJ 4456 [Zjoi2016]旅行者
- 【分治+最短路】UOJ#184【ZJOI2016】旅行者
- bzoj 4456: [Zjoi2016]旅行者
- 4456: [Zjoi2016]旅行者
- BZOJ4456 ZJOI2016旅行者(分治+最短路)
- BZOJ4456/UOJ184 [Zjoi2016]旅行者
- UOJ 184 [ZJOI2016]旅行者
- 4456: [Zjoi2016]旅行者
- BZOJ 4456 [Zjoi2016]旅行者
- 【BZOJ4456】[Zjoi2016]旅行者 分治+最短路
- BZOJ.4456.[ZJOI2016]旅行者(分治 Dijkstra)
- 【BZOJ 4456】【UOJ #184】【ZJOI 2016】旅行者
- Bzoj4456 [Zjoi2016]旅行者