题意:
在一个三维空间中,存在一个长方体,但并不知道它的具体位置,但有n个点在长方体内,m个点不在长方体内,先判断是否合法,若合法再给出k组询问,每次询问某个点是否在长方体内(回答在,不在,或不确定)
分析:
诶。。这次B、C题被hack了,不然就有时间做这题了。。。。想哭
其实这题也不难。
首先根据n个在长方体内的点,确定长方体每个维度坐标的最小值&最大值。
如果一个点满足 xmin≤x≤xmax且ymin≤y≤ymax且zmin≤z≤zmax x m i n ≤ x ≤ x m a x 且 y m i n ≤ y ≤ y m a x 且 z m i n ≤ z ≤ z m a x ,那么其必然在长方体内。
先通过这个判断那m个点是否合法。
然后把这m个点存起来。
对于每次询问,如果满足一定在长方体内的条件,直接输出。
否则先假设它在长方体内,并通过它得到一个新的 xmin,xmax,ymin,ymax,zmin,zmax x m i n , x m a x , y m i n , y m a x , z m i n , z m a x
然后判断这个新的范围是否会让那m个点中的任意一个非法。
如果合法(即新的范围内仍然没有m中的点),那么答案就是不确定
如果非法(即新的范围中有m中的点),答案就是不存在长方体中。
当然,每次询问后范围都要恢复。
具体实现。。。用KD树就可以了。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<vector>
#define SF scanf
#define PF printf
#define MAXN 100010
using namespace std;
struct node{
int minx[4],maxx[4],d[4];
int l,r;
update(const node &a){
for(int i=0;i<3;i++){
minx[i]=min(minx[i],a.minx[i]);
maxx[i]=max(maxx[i],a.maxx[i]);
}
}
}t[MAXN];
int D;
bool cmp(const node& a,const node &b){
if(a.d[D]!=b.d[D])
return a.d[D]<b.d[D];
if(a.d[(D+1)%3]!=b.d[(D+1)%3])
return a.d[(D+1)%3]<b.d[(D+1)%3];
return a.d[(D+2)%3]<b.d[(D+2)%3];
}
int build(int l,int r,int nowd){
int mid=(l+r)>>1;
D=nowd;
nth_element(t+l,t+mid,t+r+1,cmp);
for(int i=0;i<3;i++)
t[mid].maxx[i]=t[mid].minx[i]=t[mid].d[i];
if(l<mid){
t[mid].l=build(l,mid-1,(nowd+1)%3);
t[mid].update(t[t[mid].l]);
}
if(r>mid){
t[mid].r=build(mid+1,r,(nowd+1)%3);
t[mid].update(t[t[mid].r]);
}
return mid;
}
int minval[4],maxval[4];
bool check_intersect(int l1,int r1,int l2,int r2){
if(l1>r2||l2>r1)
return 0;
return 1;
}
bool check_intersect(const node &a){
for(int i=0;i<3;i++)
if(check_intersect(a.minx[i],a.maxx[i],minval[i],maxval[i])==0)
return 0;
return 1;
}
bool check_contain(int l1,int r1,int l2,int r2){
if(l2<=l1&&r1<=r2)
return 1;
return 0;
}
bool check_contain(const node &a){
for(int i=0;i<3;i++)
if(check_contain(a.minx[i],a.maxx[i],minval[i],maxval[i])==0)
return 0;
return 1;
}
bool query(int x){
if(x==0)
return 0;
if(check_intersect(t[x])==0)
return 0;
if(check_contain(t[x]))
return 1;
if(minval[0]<=t[x].d[0]&&t[x].d[0]<=maxval[0]&&minval[1]<=t[x].d[1]&&t[x].d[1]<=maxval[1]&&minval[2]<=t[x].d[2]&&t[x].d[2]<=maxval[2])
return 1;
if(query(t[x].l))
return 1;
if(query(t[x].r))
return 1;
return 0;
}
int minx,miny,minz,maxx,maxy,maxz;
int main(){
int n,m,k;
int x,y,z;
SF("%d%d%d%d%d%d",&x,&y,&z,&n,&m,&k);
minx=x;
miny=y;
minz=z;
maxx=1;
maxy=1;
maxz=1;
for(int i=1;i<=n;i++){
SF("%d%d%d",&x,&y,&z);
minx=min(minx,x);
miny=min(miny,y);
minz=min(minz,z);
maxx=max(maxx,x);
maxy=max(maxy,y);
maxz=max(maxz,z);
}
int tot=0;
for(int i=1;i<=m;i++){
SF("%d%d%d",&x,&y,&z);
if(minx<=x&&x<=maxx&&miny<=y&&y<=maxy&&minz<=z&&z<=maxz){
PF("INCORRECT");
return 0;
}
tot++;
t[tot].d[0]=x;
t[tot].d[1]=y;
t[tot].d[2]=z;
}
PF("CORRECT\n");
int rt=build(1,tot,0);
for(int i=1;i<=k;i++){
SF("%d%d%d",&x,&y,&z);
if(minx<=x&&x<=maxx&&miny<=y&&y<=maxy&&minz<=z&&z<=maxz){
PF("OPEN\n");
}
else{
minval[0]=min(minx,x);
minval[1]=min(miny,y);
minval[2]=min(minz,z);
maxval[0]=max(maxx,x);
maxval[1]=max(maxy,y);
maxval[2]=max(maxz,z);
if(query(rt))
PF("CLOSED\n");
else
PF("UNKNOWN\n");
}
}
}