抓企鹅
时间限制: 2 Sec 内存限制: 256 MB
题目描述
Xyz带着他的教徒们乘着科考船一路破冰来到了南极大陆,发现这里有许许多多的企鹅。邪恶的Xyz想要抓很多企鹅回去开动物园,当宠物玩。但动物保护协会很快赶来,他必须尽快行动!
我们把南极大陆看成一个三维直角坐标系。
有N只企鹅,每只企鹅会在一定的时刻的出现,第i只企鹅在Ai时刻出现在坐标为(Bi,Ci,Di)的地方。
Xyz要在某一时刻在某一地方(X,Y,Z)撒一张大网,将(0,0,0)到(X,Y,Z)这个大长方体里的企鹅全都网进去捕捉回家(还没出现的企鹅就不会被捉进去了)。
为了快准狠而且保证不铺张浪费网,Xyz想知道不同时间不同地点撒网能抓到几个企鹅(这样的询问有Q个)。然后他再行动。
输入
第一行一个整数N表示企鹅个数。
第二行到N+1行每行四个实数(Ai,Bi,Ci,Di),表示企鹅的出现时间和位置
第N+2行一个整数Q表示询问个数。
接下来Q行每行四个实数(T,X,Y,Z),表示询问的时间和位置。
输出
输出共Q行,每行一个整数,回答每个询问能抓到几个企鹅。
样例输入
1
0 0 0 0
2
1 1 1 1.0
1 1 1 -1
样例输出
1
0
【数据规模和约定】
共20个数据
数据1~3 N,Q<=1000
数据4~6 N,Q<=5000
数据7~10 N,Q<=10000
数据11~14 N<=30000,Q<=10000
数据15~18 N<=10000,Q<=30000
数据19~20 N,Q<=30000
题解
分治套分治套树状数组,分别维护x坐标,y坐标,z坐标。
代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<algorithm>
#define N 30010
using namespace std;
int n,m,Tnum,C[N*2],ans[N];
double h[N*2],num[N*2];
struct node{
int type,pos,c;double x,a,b;
bool operator<(const node &wbs)const{
if(x!=wbs.x)return x<wbs.x;
if(a!=wbs.a)return a<wbs.a;
if(b!=wbs.b)return b<wbs.b;
if(c!=wbs.c)return c<wbs.c;
return type<wbs.type;
}
}t[N*2],tp[N*2],p[N*2];
class bit
{
public:
void modify(int x,int val)
{
for(;x<=Tnum;x+=x&-x)C[x]+=val;
}
int qry(int x)
{
int res=0;
for(;x;x-=x&-x)res+=C[x];
return res;
}
}T;
void solve2(int l,int r)
{
if(l==r)return;
int mid=l+r>>1,lx=l,rx=mid+1,tot=0;
solve2(l,mid);solve2(mid+1,r);
while(rx<=r)
{
if(lx<=mid&&tp[lx].b<=tp[rx].b)
{
if(!tp[lx].type)T.modify(tp[lx].c,1);
p[++tot]=tp[lx];lx++;
}
else
{
if(tp[rx].type)ans[tp[rx].pos]+=T.qry(tp[rx].c);
p[++tot]=tp[rx];rx++;
}
}
for(int i=l;i<lx;i++)
if(!tp[i].type)T.modify(tp[i].c,-1);
while(lx<=mid)p[++tot]=tp[lx],lx++;
for(int i=l;i<=r;i++)tp[i]=p[i-l+1];
}
void solve(int l,int r)
{
if(l==r)return;
int mid=l+r>>1,lx=l,rx=mid+1,tot=0,num=0;
solve(l,mid);solve(mid+1,r);
while(rx<=r)
{
if(lx<=mid&&t[lx].a<=t[rx].a)
{
if(!t[lx].type)tp[++num]=t[lx];
p[++tot]=t[lx];lx++;
}
else
{
if(t[rx].type)tp[++num]=t[rx];
p[++tot]=t[rx];rx++;
}
}
while(lx<=mid)p[++tot]=t[lx],lx++;
for(int i=l;i<=r;i++)t[i]=p[i-l+1];
if(num)solve2(1,num);
}
int main()
{
double x,a,b,c;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%lf%lf%lf%lf",&x,&a,&b,&c);
t[i]=(node){0,0,0,x,a,b};h[i]=c;num[i]=c;
}
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
scanf("%lf%lf%lf%lf",&x,&a,&b,&c);
t[i+n]=(node){1,i,0,x,a,b};h[i+n]=c;num[i+n]=c;
}
n+=m;sort(h+1,h+n+1);
Tnum=unique(h+1,h+n+1)-h-1;
for(int i=1;i<=n;i++)
t[i].c=lower_bound(h+1,h+Tnum+1,num[i])-h;
sort(t+1,t+n+1);
solve(1,n);
for(int i=1;i<=m;i++)printf("%d\n",ans[i]);
return 0;
}