当前位置: 代码迷 >> 综合 >> 【KD树】Codeforces499Div1 CF1010E Store
  详细解决方案

【KD树】Codeforces499Div1 CF1010E Store

热度:115   发布时间:2023-09-27 07:06:40.0

题意:

在一个三维空间中,存在一个长方体,但并不知道它的具体位置,但有n个点在长方体内,m个点不在长方体内,先判断是否合法,若合法再给出k组询问,每次询问某个点是否在长方体内(回答在,不在,或不确定)


分析:

诶。。这次B、C题被hack了,不然就有时间做这题了。。。。想哭

其实这题也不难。

首先根据n个在长方体内的点,确定长方体每个维度坐标的最小值&最大值。

如果一个点满足xminxxmaxyminyymaxzminzzmaxxmin≤x≤xmax且ymin≤y≤ymax且zmin≤z≤zmax,那么其必然在长方体内。

先通过这个判断那m个点是否合法。

然后把这m个点存起来。

对于每次询问,如果满足一定在长方体内的条件,直接输出。

否则先假设它在长方体内,并通过它得到一个新的xmin,xmax,ymin,ymax,zmin,zmaxxmin,xmax,ymin,ymax,zmin,zmax

然后判断这个新的范围是否会让那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");elsePF("UNKNOWN\n");    }}
}
  相关解决方案