[NEERC 2015] bzoj4449 Distance on Triangulation [分治+最短路]
2018-03-25 21:15
465 查看
Description:
给定一个凸nn边形,以及它的三角剖分。再给定qq个询问,每个询问是一对凸多边行上的顶点(a,b)(a,b),问点aa最少经过多少条边(可以是多边形上的边,也可以是剖分上的边)可以到达点bb。
Solution:
看起来很难写,其实想清楚还是比较好写的。
我们可以对每个多边形进行分治,每次选择其中的一个分的最均匀的对角线,以其两个顶点做最短路,并更新跨过这条对角线的所有询问,这些询问取到最小值肯定也是经过这条对角线。这样分治只需要nlognnlogn的时间可以解决所有询问。分治时要记录当前多边形中的对角线,点,还有询问,求最短路时只要把当前区间里的点求最短路,否则时间复杂度不对。点则是为了在求最短路和分治区间时判断是否属于当前区间。
代码几乎是抄的,主要是结构。
分治主要思想是把一些有相同点的问题通过预处理批量处理,比如这里就是经过对角线的询问,先预处理出两点的最短路,复杂度很低,然后其他的就可以批量预处理了。
cdq分治也是,找出一些操作,其中一部分都受到另一部分影响,所以把前一部分通过数据结构预处理,这样就不用两两重复操作了。
给定一个凸nn边形,以及它的三角剖分。再给定qq个询问,每个询问是一对凸多边行上的顶点(a,b)(a,b),问点aa最少经过多少条边(可以是多边形上的边,也可以是剖分上的边)可以到达点bb。
Solution:
看起来很难写,其实想清楚还是比较好写的。
我们可以对每个多边形进行分治,每次选择其中的一个分的最均匀的对角线,以其两个顶点做最短路,并更新跨过这条对角线的所有询问,这些询问取到最小值肯定也是经过这条对角线。这样分治只需要nlognnlogn的时间可以解决所有询问。分治时要记录当前多边形中的对角线,点,还有询问,求最短路时只要把当前区间里的点求最短路,否则时间复杂度不对。点则是为了在求最短路和分治区间时判断是否属于当前区间。
代码几乎是抄的,主要是结构。
分治主要思想是把一些有相同点的问题通过预处理批量处理,比如这里就是经过对角线的询问,先预处理出两点的最短路,复杂度很低,然后其他的就可以批量预处理了。
cdq分治也是,找出一些操作,其中一部分都受到另一部分影响,所以把前一部分通过数据结构预处理,这样就不用两两重复操作了。
#include <bits/stdc++.h> using namespace std; const int N = 5e5 + 5, inf = 1e9; struct data { int l, r, id; } q , E , tmp1 , tmp2 , tmp3 , tmp4 ; int n, m; int ans , B , d1 , d2 , tmp5 , tmp6 ; vector<int> G ; queue<int> que; int check(int l, int r, int x) { return lower_bound(B + l, B + r + 1, x) - B; } void bfs(int l, int r, int s, int *d) { for(int i = l; i <= r; ++i) { d[B[i]] = inf; } d[s] = 0; que.push(s); while(!que.empty()) { int u = que.front(); que.pop(); for(int i = 0; i < G[u].size(); ++i) { int v = G[u][i]; if(d[v] == inf && B[check(l, r, v)] == v) { d[v] = d[u] + 1; que.push(v); } } } } int get_ans(int u, int v) { return min(min(d1[u] + d1[v], d2[u] + d2[v]), min(d1[u] + 1 + d2[v], d1[v] + 1 + d2[u])); } void cdq(int l, int r, int x, int y, int a, int b) { if(l > r || x > y) { return; } int mn = inf, pos; for(int i = l; i <= r; ++i) { int p = check(x, y, E[i].l), q = check(x, y, E[i].r); if(p > q) { swap(p, q); } int tmp = max(q - p + 1, y - x + 1 - q + p); if(tmp < mn) { mn = tmp; pos = i; } } int L = E[pos].l, R = E[pos].r, tot1 = 0, tot2 = 0, tot3 = 0, tot4 = 0, tot5 = 0, tot6 = 0; bfs(x, y, L, d1); bfs(x, y, R, d2); for(int i = a; i <= b; ++i) { if(q[i].l == L && q[i].r == R) { ans[q[i].id] = 1; continue; } ans[q[i].id] = min(ans[q[i].id], get_ans(q[i].l, q[i].r)); if(q[i].l > L && q[i].r < R) { tmp1[++tot1] = q[i]; } else if((q[i].l > R && q[i].r > R) || (q[i].l < L && q[i].r > R) || (q[i].r < L)) { tmp2[++tot2] = q[i]; } } for(int i = 1; i <= tot1; ++i) { q[a + i - 1] = tmp1[i]; } for(int i = 1; i <= tot2; ++i) { q[a + tot1 + i - 1] = tmp2[i]; } for(int i = l; i <= r; ++i) { if(i != pos) { if(E[i].l >= L && E[i].r <= R) { tmp3[++tot3] = E[i]; } else { tmp4[++tot4] = E[i]; } } } for(int i = 1; i <= tot3; ++i) { E[l + i - 1] = tmp3[i]; } for(int i = 1; i <= tot4; ++i) { E[l + tot3 + i - 1] = tmp4[i]; } for(int i = x; i <= y; ++i) { if(B[i] >= L && B[i] <= R) { tmp5[++tot5] = B[i]; } else { tmp6[++tot6] = B[i]; } } for(int i = 1; i <= tot5; ++i) { B[x + i - 1] = tmp5[i]; } for(int i = 1; i <= tot6; ++i) { B[x + tot5 + i - 1] = tmp6[i]; } cdq(l, l + tot3 - 1, x, x + tot5 - 1, a, a + tot1 - 1); cdq(l + tot3, l + tot3 + tot4 - 1, x + tot5, x + tot5 + tot6 - 1, a + tot1, a + tot1 + tot2 - 1); } int main() { // freopen("distance.in", "r", stdin); // freopen("distance.out", "w", stdout); scanf("%d", &n); for(int i = 1; i <= n - 3; ++i) { int u, v; scanf("%d%d", &u, &v); if(u > v) { swap(u, v); } G[u].push_back(v); G[v].push_back(u); E[i].l = u; E[i].r = v; } for(int i = 1; i <= n; ++i) { B[i] = i; G[i].push_back(i % n + 1); G[i % n + 1].push_back(i); } scanf("%d", &m); for(int i = 1; i <= m; ++i) { scanf("%d%d", &q[i].l, &q[i].r); q[i].id = i; if(q[i].l > q[i].r) { swap(q[i].l, q[i].r); } ans[i] = min(q[i].r - q[i].l, n + q[i].l - q[i].r); } cdq(1, n - 3, 1, n, 1, m); for(int i = 1; i <= m; ++i) { printf("%d\n", ans[i]); } // fclose(stdin); // fclose(stdout); return 0; }
相关文章推荐
- [BZOJ4449][Neerc2015][分治][最短路]Distance on Triangulation
- [点分治 离线] BZOJ 4449 [Neerc2015]Distance on Triangulation
- 【BZOJ 4449】[Neerc2015]Distance on Triangulation 多边形分治结构
- BZOJ4449: [Neerc2015]Distance on Triangulation
- bzoj 4449: [Neerc2015]Distance on Triangulation
- BZOJ4449 : [Neerc2015]Distance on Triangulation
- 【bzoj 4449】[Neerc2015]Distance on Triangulation
- 图例练习题:【BZOJ3889】【Usaco2015 Jan】Cow Routing 双键值最短路
- CC Prime Distance On Tree (树的点分治 + FFT)
- BZOJ_4016_[FJOI2014]最短路径树问题_最短路+点分治
- 【BZOJ4430】[Nwerc2015]Guessing Camels赌骆驼【树状数组】【或CDQ分治】
- 【bzoj3924】[Zjoi2015]幻想乡战略游戏 动态点分治
- [Usaco2015 Feb] bzoj3939 Cow Hopscotch [cdq分治]
- [BZOJ3889]USACO2015 Jan-Cow|最短路
- [动态树分治] BZOJ4012 [HNOI2015]开店
- [BZOJ4012][HNOI2015]开店(动态点分治)
- 【bzoj4070】【APIO2015】【雅加达的摩天楼】【最短路】
- bzoj2015 [Usaco2010 Feb]Chocolate Giving(最短路裸题)
- bzoj 3931: [CQOI2015]网络吞吐量(最短路+网络流)
- codechef Prime Distance On Tree(树分治+FFT)