jzoj100048 【NOIP2017提高A组模拟7.14】紧急撤离 (网格图,分治,bitSet)
来源:互联网 发布:熊掌好吃吗 知乎 编辑:程序博客网 时间:2024/06/05 03:07
题意
给出一个n*m <=500*500的网格图,有一些点有障碍。从一个点只能向下,向右走,询问
分析
询问这么多,如果不是并查集的话一定是预处理了。
考虑直接做,对于每一个询问要nm的时间来暴力。
优化?
枚举一个中间点,然后向两边寻找。
如何配对询问?
将询问用边集数组之类的打到点上。再用O(q)时间询问。 这样我们就切掉了这题 才怪咧,一个点的时间是
等等
不一定经过定点
但是在那一列两侧的一定经过那一列!
考虑分治
将从列
经过中间的如何计算?
暴力还是n3的,考虑dp。发现dp也可以求出一个点(x,y)能到中间点的哪些点。
但如果dp使用bitset压位优化,时间就可以除掉一个常数32。
这样分下去可以分log m次,不难看出每一层都是
询问需要保证只会被访问一次,所以插入边集数组时有排序姿势。
CODE
#include <iostream>#include <cstdio>#include <bitset>#include <cstring>#include <algorithm>#define N 510using namespace std;bitset<N> bs[N][N];int n,m,q,ans[600001],tot;int next[600001],head[N][N];bool map[N][N];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");}
阅读全文
2 0
- jzoj100048 【NOIP2017提高A组模拟7.14】紧急撤离 (网格图,分治,bitSet)
- 【NOIP2017提高A组模拟7.14】紧急撤离
- 【JZOJ100048】紧急撤离
- 【jzoj5328】【NOIP2017提高A组模拟8.22】【世界线】【bitset】
- JZOJ5399. 【NOIP2017提高A组模拟10.7】Confess bitset
- 【jzoj5338】【NOIP2017提高A组模拟8.25】【影子】【点分治】
- 【NOIP2017提高A组模拟7.7】图
- 5328. 【NOIP2017提高A组模拟8.22】世界线 bitset+拓补序合并
- [jzoj100047]【NOIP2017提高A组模拟7.14】基因变异
- JZOJ 100046. 【NOIP2017提高A组模拟7.14】收集卡片
- JZOJ 100047. 【NOIP2017提高A组模拟7.14】基因变异
- JZOJ100046. 【NOIP2017提高A组模拟7.14】收集卡片
- JZOJ100047. 【NOIP2017提高A组模拟7.14】基因变异
- JZOJ 100026. 【NOIP2017提高A组模拟7.7】图
- 【NOIP2017提高A组模拟9.7】简单无向图
- A【NOIP2017提高组模拟12.18】
- 【JZOJ4928】【NOIP2017提高组模拟12.18】A
- 【NOIP2017提高组模拟12.18】A
- laravel部分命令
- pycaffe使用(第一篇)——训练网络
- 集合List<E>转换成对应元素类型的数组E[]
- NFS vs. CIFS
- 如何找到文件版本号,以及如何在vs工程中设置(查找)版本号
- jzoj100048 【NOIP2017提高A组模拟7.14】紧急撤离 (网格图,分治,bitSet)
- 算法练习----杨辉三角(1)
- 合并两个有序的单链表
- java中为什么使用上转型和下转型
- 启动Tomcat报错:
- 成绩排名
- 简单介绍下BS与CS的联系与区别。
- android 之sqlite数据库的创建
- 【视觉-摄像机3】}摄像机镜头--焦距与视角(选相机和镜头)