BZOJ3567 : AABB
考虑以块大小为$32$将序列分块,设$s[i][j]$表示前$i$块和前$j$块矩形相交的对数,$f[i][j]$表示矩形$i$和前$j$块的相交个数。
如果矩形$i$和$j$相交,那么有:
$x_1[j] < x_2[i]$
$x_2[j] > x_1[i]$
$y_1[j] < y_2[i]$
$y_2[j] > y_1[i]$
将这$4$维分开处理,对于每一维按相应参数排序,维护一个集合,支持加入以及求交。这显然可以通过bitset在$O(\frac{n^2}{32})$的时间内完成。
通过bitset求出某个矩形$i$和所有矩形的相交情况后,即可在$O(\frac{n}{32})$的时间内更新$s$和$f$。
然后对$s$和$f$求前缀和即可完成$s$和$f$的预处理。
对于查询,首先整块的部分可以通过$s$查询,然后暴力往右往上扩展,用$f$做到$O(1)$询问。对于块内零散部分,暴力检验即可。
每次查询的复杂度为$O(32^2)$。
因为$n$个bitset存不下,注意到bitset加入元素是$O(1)$的,所以考虑再次分块。每加入$128$个元素后备份一次,即可满足内存限制。
总时间复杂度$O(\frac{n^2}{32}+q\times 32^2)$。
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=30000,M=938,MAXB=235;
int n,m,block,i,j,k,l,r,cnt[65536],s[M][M],ans;
int A[N],B[N],C[N],D[N],E[N];
unsigned short f[N][M];
struct P{int x1,y1,x2,y2;}a[N];
inline bool cmpa(int x,int y){return a[x].x1<a[y].x1;}
inline bool cmpb(int x,int y){return a[x].x2>a[y].x2;}
inline bool cmpc(int x,int y){return a[x].y1<a[y].y1;}
inline bool cmpd(int x,int y){return a[x].y2>a[y].y2;}
inline bool cmpe(int x,int y){return a[x].y1>a[y].y1;}
inline int popcount(unsigned int x){return cnt[x&65535]+cnt[x>>16];}
struct Bitset{
unsigned int v[M];
Bitset(){}
inline void clear(){for(int i=0;i<=m;i++)v[i]=0;}
inline void set(int x){v[x>>5]|=1U<<(x&31);}
inline void copy(const Bitset&p){for(int i=0;i<=m;i++)v[i]=p.v[i];}
inline void operator&=(const Bitset&p){for(int i=0;i<=m;i++)v[i]&=p.v[i];}
}bA[MAXB],bB[MAXB],bC[MAXB],bD,now,tmp;
inline bool check(const P&a,const P&b){
return b.x1<a.x2&&b.x2>a.x1&&b.y1<a.y2&&b.y2>a.y1;
}
inline int ask(int x,int y){
if(x<0||y<0)return 0;
int ret=0,c=x>>5<<5,d=y>>5<<5,i,j;
if(x>31&&y>31)ret=s[(x>>5)-1][(y>>5)-1];
for(i=c;i<=x;i++)for(j=d;j<=y;j++)if(check(a[i],a[j]))ret++;
if(x>31)for(i=d;i<=y;i++)ret+=f[i][(x>>5)-1];
if(y>31)for(i=c;i<=x;i++)ret+=f[i][(y>>5)-1];
return ret;
}
inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
int main(){
read(n);
for(i=0;i<n;i++)read(a[i].x1),read(a[i].y1),read(a[i].x2),read(a[i].y2);
m=(n-1)>>5;
for(i=1;i<65536;i++)cnt[i]=cnt[i>>1]+(i&1);
block=(n-1)>>7;
for(i=0;i<n;i++)A[i]=i;
sort(A,A+n,cmpa);
for(i=0;i<=block;i++){
l=i<<7,r=min(l+128,n);
if(i)bA[i].copy(bA[i-1]);
while(l<r)bA[i].set(A[l++]);
}
for(i=0;i<n;i++)B[i]=i;
sort(B,B+n,cmpb);
for(i=0;i<=block;i++){
l=i<<7,r=min(l+128,n);
if(i)bB[i].copy(bB[i-1]);
while(l<r)bB[i].set(B[l++]);
}
for(i=0;i<n;i++)C[i]=i;
sort(C,C+n,cmpc);
for(i=0;i<=block;i++){
l=i<<7,r=min(l+128,n);
if(i)bC[i].copy(bC[i-1]);
while(l<r)bC[i].set(C[l++]);
}
for(i=0;i<n;i++)D[i]=E[i]=i;
sort(D,D+n,cmpd);
sort(E,E+n,cmpe);
for(i=j=0;i<n;i++){
int x=E[i];P&y=a[x];
while(j<n&&a[D[j]].y2>y.y1)bD.set(D[j++]);
now.copy(bD);
for(k=0;k<=block;k++){
r=min(k<<7|127,n-1);
if(a[A[r]].x1>=y.x2)break;
}
if(k)tmp.copy(bA[k-1]);else tmp.clear();
if(k<=block){
l=k<<7;
while(a[A[l]].x1<y.x2)tmp.set(A[l++]);
}
now&=tmp;
for(k=0;k<=block;k++){
r=min(k<<7|127,n-1);
if(a[B[r]].x2<=y.x1)break;
}
if(k)tmp.copy(bB[k-1]);else tmp.clear();
if(k<=block){
l=k<<7;
while(a[B[l]].x2>y.x1)tmp.set(B[l++]);
}
now&=tmp;
for(k=0;k<=block;k++){
r=min(k<<7|127,n-1);
if(a[C[r]].y1>=y.y2)break;
}
if(k)tmp.copy(bC[k-1]);else tmp.clear();
if(k<=block){
l=k<<7;
while(a[C[l]].y1<y.y2)tmp.set(C[l++]);
}
now&=tmp;
for(k=0;k<=m;k++){
f[x][k]=popcount(now.v[k]);
s[x>>5][k]+=f[x][k];
if(k)f[x][k]+=f[x][k-1];
}
}
for(i=0;i<=m;i++)for(j=0;j<=m;j++){
if(i)s[i][j]+=s[i-1][j];
if(j)s[i][j]+=s[i][j-1];
if(i&&j)s[i][j]-=s[i-1][j-1];
}
read(m);
while(m--){
read(i),read(j),read(l),read(r);
i^=ans,j^=ans,l^=ans,r^=ans;
i--,j--,l--,r--;
printf("%d\n",ans=ask(j,r)-ask(i-1,r)-ask(j,l-1)+ask(i-1,l-1));
}
return 0;
}
BZOJ3567 : AABB的更多相关文章
- [算法][包围盒]AABB简单类
头文件: #pragma once #include <iostream> //一个假的点类型 struct Vector3 { float x; float y; float z; }; ...
- [算法][包围盒]球,AABB,OBB
参考地址请看图片水印:http://www.cnblogs.com/iamzhanglei/archive/2012/06/07/2539751.html http://blog.sina.com.c ...
- JAVA智能设备基于OpenGL的3D开发技术 之AABB碰撞检测算法论述
摘要:无论是PC机的3D还是智能设备应用上,碰撞检测始终是程序开发的难点,甚至可以用碰撞检测作为衡量3D引擎是否完善的标准.现有许多3D碰撞检测算法,其中AABB碰撞检测是一种卓有成效而又经典的检测算 ...
- TC SRM 663 div2 B AABB 逆推
AABB Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 TC Description One day, Jamie noticed that many En ...
- AABB碰撞盒
矩形边界框(转) 另一种常见的用来界定物体的几何图元是矩形边界框,矩形边界框可以是与轴对齐的或是任意方向的.轴对齐矩形边界框有一个限制,就是它的边必须垂直于坐标轴.缩写AABB常用来表示axially ...
- AABB包围盒、OBB包围盒、包围球的比較
1) AABB 包围盒: AABB 包围盒是与坐标轴对齐的包围盒, 简单性好, 紧密性较差(尤其对斜对角方向放置的瘦长形对象, 採用AABB, 将留下非常大的边角空隙, 导致大量不是必需的包围盒相交測 ...
- 3D空间中的AABB(轴向平行包围盒, Aixe align bounding box)的求法
引言 在前面的一篇文章中讲述了怎样通过模型的顶点来求的模型的包围球,而且还讲述了基本包围体除了包围球之外,还有AABB包围盒.在这一章,将讲述怎样依据模型的坐标求得它的AABB盒. 表示方法 AABB ...
- 3D空间中射线与轴向包围盒AABB的交叉检测算法【转】
引言 在上一节中,我讲述了如何实现射线与三角形的交叉检测算法.但是,我们应该知道,在游戏开发中,一个模型有很多的三角形构成,如果要对所有的物体,所有的三角形进行这种检测,就算现在的计算机运算能力,也是 ...
- 快速变幻AABB的顶点
[快速变幻AABB的顶点] 当要变幻一个AABB时,可以快速计算变幻后顶点的AABB.当有旋转时,根据8个顶点变幻后的AABB可能会更大. AABB的八个顶点需分别作如下变幻: 注意到为了使 x' 最 ...
随机推荐
- 三、jQuery--jQuery基础--jQuery基础课程--第5章 jQuery 操作DOM元素
1.使用attr()方法控制元素的属性 attr()方法的作用是设置或者返回元素的属性,其中attr(属性名)格式是获取元素属性名的值,attr(属性名,属性值)格式则是设置元素属性名的值. 例如,使 ...
- AIX 配置网卡
ifconfig en0 10.1.1.100 netmask 255.255.255.0 alias
- java 泛型 -- 泛型类,泛型接口,泛型方法
泛型T泛型的许多最佳例子都来自集合框架,因为泛型让您在保存在集合中的元素上指定类型约束.在定义泛型类或声明泛型类的变量时,使用尖括号来指定形式类型参数.形式类型参数与实际类型参数之间的关系类似于形式方 ...
- 【JAVA之泛型】
一.引例. 1.引例. 假设现在有一个ArrayList的容器,如果不使用泛型约束,则可以向容器中加入各种类型的对象,但是如果取出来的时候只是用一种类型的转换则肯定会抛出ClassCastExcept ...
- java中常用的工具类(二)
下面继续分享java中常用的一些工具类,希望给大家带来帮助! 1.FtpUtil Java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ...
- VS2015 Xamarin for iOS
VS2015环境配置 VS2015安装不多说.其实Xamarin 和微软感觉并不是什么好基友,Xamarin以前一直像个可怜的娃,以插件的形式寄生于VS中.现在只不过形势稍微好点了,VS2015 在明 ...
- 数据结构之图 Part2 - 2
邻接表 using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ...
- hdu 4025 2011上海赛区网络赛E 压缩 ***
直接T了,居然可以这么剪枝 题解链接:点我 #include<cstdio> #include<map> #include<cstring> #define ll ...
- RTP/RTCP的时间同步机制
转自:http://blog.csdn.net/leesphone/article/details/5571972 RTP支持传送不同codec的steaming,不同codec的clock rate ...
- struct和typedef struct
转自:http://www.cnblogs.com/qyaizs/articles/2039101.html struct和typedef struct 分三块来讲述: 1 首先://注意在C和C++ ...