jzoj100048 【NOIP2017提高A组模拟7.14】紧急撤离 (网格图,分治,bitSet)
2017-07-14 20:19
441 查看
题意
给出一个n*m <=500*500的网格图,有一些点有障碍。从一个点只能向下,向右走,询问q<=6∗105:(a,b)是否能到达(c,d)。分析
询问这么多,如果不是并查集的话一定是预处理了。考虑直接做,对于每一个询问要nm的时间来暴力。
优化?
枚举一个中间点,然后向两边寻找。
如何配对询问?
将询问用边集数组之类的打到点上。再用O(q)时间询问。
这样我们就切掉了这题 才怪咧,一个点的时间是O(n2),整张图是多少?
等等
不一定经过定点
但是在那一列两侧的一定经过那一列!
考虑分治
将从列mid切开,如果不经过中间的就左右两个区间分治搞。
经过中间的如何计算?
暴力还是n3的,考虑dp。发现dp也可以求出一个点(x,y)能到中间点的哪些点。
O(n3)
但如果dp使用bitset压位优化,时间就可以除掉一个常数32。
T(m)=2T(m2)+n2m/32
这样分下去可以分log m次,不难看出每一层都是n2m/32,所以最后时间复杂度就是O(n2m logm /32+q),也就是O(n3+q)。 从这里可以发现如果不用bitset那么时间就会多一个log,会T得飞起。
询问需要保证只会被访问一次,所以插入边集数组时有排序姿势。
CODE
#include <iostream> #include <cstdio> #include <bitset> #include <cstring> #include <algorithm> #define N 510 using namespace std; bitset<N> bs ; int n,m,q,ans[600001],tot; int next[600001],head ; bool map ; struct req{ int lx,ly,rx,ry,to; } a[600001],re[600001]; bool cmp(req x,req y) {return x.ry<y.ry;} void link(int x,int y,const req &r) { re[++tot]=r; next[tot]=head[x][y]; head[x][y]=tot; } void init() { cin>>n>>m; char c; for (int i=1; i<=n; i++) { scanf("\n"); for (int j=1; j<=m; j++) { c=getchar(); map[i][j]=1-(c-'0'); } } cin>>q; for (int i=1; i<=q; i++) scanf("%d %d %d %d",&a[i].lx,&a[i].ly,&a[i].rx,&a[i].ry),a[i].to=i; sort(a+1,a+1+q,cmp); for (int i=q; i; i--) link(a[i].lx,a[i].ly,a[i]); } void divide(int l,int r) { if (l>r) return; int mid=l+r>>1; divide(l,mid-1); divide(mid+1,r); for (int i=1; i<=n; i++) for (int j=l; j<=r; j++) bs[i][j].reset(); for (int i=1; i<=n; i++) if (map[i][mid]) bs[i][mid].set(i); for (int j=mid; j>=l; j--) for (int i=n; i; i--) if (map[i][j]) bs[i][j]|=bs[i+1][j] | bs[i][j+1]; for (int i=1; i<=n; i++) { bs[i][mid].reset(); if (map[i][mid]) bs[i][mid].set(i); } for (int j=mid; j<=r; j++) for (int i=1; i<=n; i++) if (map[i][j]) { bs[i][j]|=bs[i-1][j]; if (j!=mid) bs[i][j]|=bs[i][j-1]; } for (int i=1; i<=n; i++) for (int j=l; j<=mid; j++) { for (int z=head[i][j]; z; z=next[z]) { if (re[z].ry>r) break; head[i][j]=next[z]; if (re[z].ry==re[z].ly) ans[re[z].to]=bs[re[z].rx][re[z].ry][re[z].lx]; else if (re[z].ry==mid) ans[re[z].to]=bs[i][j][re[z].rx]; else if (j==mid) ans[re[z].to]=bs[re[z].rx][re[z].ry][re[z].lx]; else if ((bs[i][j] & bs[re[z].rx][re[z].ry]).any()) ans[re[z].to]=1; } } } int main() { freopen("3.in","r",stdin); freopen("3.out","w",stdout); init(); divide(1,m); for (int i=1; i<=q; i++) if (ans[i]) printf("Safe\n"); else printf("Dangerous\n"); }
相关文章推荐
- [jzoj100047]【NOIP2017提高A组模拟7.14】基因变异
- 【jzoj5328】【NOIP2017提高A组模拟8.22】【世界线】【bitset】
- 【NOIP2017提高A组模拟7.14】紧急撤离
- 【jzoj5338】【NOIP2017提高A组模拟8.25】【影子】【点分治】
- JZOJ100046. 【NOIP2017提高A组模拟7.14】收集卡片
- JZOJ100047. 【NOIP2017提高A组模拟7.14】基因变异
- JZOJ5399. 【NOIP2017提高A组模拟10.7】Confess bitset
- JZOJ 100047. 【NOIP2017提高A组模拟7.14】基因变异
- JZOJ 100046. 【NOIP2017提高A组模拟7.14】收集卡片
- 【JZOJ5335】【NOIP2017提高组模拟】早苗(DP、矩阵乘法)
- JZOJ4919. 【NOIP2017提高组模拟12.10】神炎皇
- jzoj5394 【NOIP2017提高A组模拟10.5】Ping
- JZOJ5397. 【NOIP2017提高A组模拟10.6】Biology trie+LCA/哈希
- 【JZOJ4929】 【NOIP2017提高组模拟12.18】B
- JZOJ5400. 【NOIP2017提高A组模拟10.7】Repulsed 树型DP+贪心
- 【JZOJ 4931】【NOIP2017提高组模拟12.24】A
- JZOJ5401. 【NOIP2017提高A组模拟10.8】Star Way To Heaven
- [JZOJ5405]【NOIP2017提高A组模拟10.10】Permutation
- 【jzoj5347】【NOIP2017提高A组模拟9.5】【遥远的金字塔】【斜率优化动态规划】
- [JZSC2017] 【NOIP2017提高组模拟6.28】总结