hdu5560 The Shields

Problem Description
General Zhang recently got a plasma shield to intercept incoming missiles.

The shape of the plasma shield is basically a square with a horizontal diagonal. Due to some technology issues, the plasma shield cannot protect the whole square area. One vertical stripe in the middle of the square is penetrable to the missiles. So, in fact the shield is formed by two identical isosceles right triangle. Missiles hitting the surface or the edge of the shield are considered intercepted.



Now  N  missiles are coming to General Zhang’s army. The  ith  missile will strike the position  (xi,yi) . Because he only has one plasma shield, he want to calculate when the shield is turned on in a particular way, how many of the missiles it can stop.

General Zhang will give you  M  queries, each query describe the shape of a plasma by 4 integers  (X,Y,D,W) (X,Y)  denotes the center of the shield.  D  denotes the length of the diagonal.  W  denotes the width of the unprotected stripe. For each query, you need to output number of the missiles stopped by the shield.
 

Input
The first line of input contains an integer  T  ( T20 ), which represents the number of test cases.
Each test case starts with  N  and  M  ( 1N,M20000 ) in a line. The  ith  line of the next  N  lines contains two integers  xi  and  yi . The next  M  lines each line has 4 integers  X,Y,D,W , which represents a query.  D  and  W  are guaranteed to be even numbers.
 

Output
For each test case, output a single line consisting of “ Case #X:” first.  X  is the test case number starting from 1. For each query, output the number of missiles that are intercepted in a single line. Do not output extra spaces or newlines.
 

Sample Input
  
  
1 4 3 -5 0 -4 0 -3 0 0 0 0 0 0 0 0 0 8 0 0 0 8 2
 

Sample Output
  
  
Case #1: 1 3 2
 

Source

写了个kdtree。。似乎复杂度多了两个log,hdu上并不能跑过去

如果谁的kdtree跑过去的话求告诉一下。。或者谁有数据求发一份。。我在本机测测到底跑了多久

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

大概就是把每个点转换成(x,x+y,x-y)这三个维度用kdtree维护

每个三角形都可以用这三个维度限定出来

直接用kdtree维护即可

复杂度是T*Mlog^3N。标算似乎只有一个log

先把代码贴出来吧

#include<cstdio>
#include<algorithm>
using namespace std;
struct point
{
	int p[3],y;
	int min[3],max[3];
	int ll,rr;
	int s;
}tr[50001];
int cmpd;
inline bool cmp(point x,point y)
{
	return x.p[cmpd]<y.p[cmpd];
}
inline void up(int p)
{
	int L=tr[p].ll,R=tr[p].rr;
	tr[p].min[0]=min(tr[p].min[0],tr[L].min[0]);
	tr[p].min[0]=min(tr[p].min[0],tr[R].min[0]);
	tr[p].min[1]=min(tr[p].min[1],tr[L].min[1]);
	tr[p].min[1]=min(tr[p].min[1],tr[R].min[1]);
	tr[p].min[2]=min(tr[p].min[2],tr[L].min[2]);
	tr[p].min[2]=min(tr[p].min[2],tr[R].min[2]);
	
	tr[p].max[0]=max(tr[p].max[0],tr[L].max[0]);
	tr[p].max[0]=max(tr[p].max[0],tr[R].max[0]);
	tr[p].max[1]=max(tr[p].max[1],tr[L].max[1]);
	tr[p].max[1]=max(tr[p].max[1],tr[R].max[1]);
	tr[p].max[2]=max(tr[p].max[2],tr[L].max[2]);
	tr[p].max[2]=max(tr[p].max[2],tr[R].max[2]);
	
	tr[p].s=tr[L].s+tr[R].s+1;
}
inline int build(int l,int r,int d)
{
	int mid=(l+r)/2;
	cmpd=d;
	nth_element(tr+l,tr+mid,tr+r+1,cmp);
	tr[mid].min[0]=tr[mid].p[0];
	tr[mid].min[1]=tr[mid].p[1];
	tr[mid].min[2]=tr[mid].p[2];
	tr[mid].max[0]=tr[mid].p[0];
	tr[mid].max[1]=tr[mid].p[1];
	tr[mid].max[2]=tr[mid].p[2];
	tr[mid].s=1;
	tr[mid].ll=0;
	tr[mid].rr=0;
	if(l<mid)
		tr[mid].ll=build(l,mid-1,(d+1)%3);
	if(r>mid)
		tr[mid].rr=build(mid+1,r,(d+1)%3);
	up(mid);
	return mid;
}
inline int ask(int p,int x10,int x11,int x12,int x20,int x21,int x22,int d)
{
	if(p==0)
		return 0;
	int x1[3],x2[3];
	x1[0]=x10;
	x1[1]=x11;
	x1[2]=x12;
	x2[0]=x20;
	x2[1]=x21;
	x2[2]=x22;
 	if(x1[0]>tr[p].max[0]||x1[1]>tr[p].max[1]||x1[2]>tr[p].max[2]||x2[0]<tr[p].min[0]||x2[1]<tr[p].min[1]||x2[2]<tr[p].min[2])
        return 0;
	if(x1[0]<=tr[p].min[0]&&tr[p].max[0]<=x2[0]&&x1[1]<=tr[p].min[1]&&tr[p].max[1]<=x2[1]&&x1[2]<=tr[p].min[2]&&tr[p].max[2]<=x2[2])
		return tr[p].s;
	int ans=0;
	if(x1[0]<=tr[p].p[0]&&tr[p].p[0]<=x2[0]&&x1[1]<=tr[p].p[1]&&tr[p].p[1]<=x2[1]&&x1[2]<=tr[p].p[2]&&tr[p].p[2]<=x2[2])
		ans++;
	if(x1[d]<=tr[p].p[d])
		ans+=ask(tr[p].ll,x10,x11,x12,x20,x21,x22,(d+1)%3);
	if(x2[d]>tr[p].p[d])
		ans+=ask(tr[p].rr,x10,x11,x12,x20,x21,x22,(d+1)%3);
	return ans;
}
int main()
{
	int T,k=0;
	scanf("%d",&T);
	while(T>0)
	{
		T--;
		k++;
		int n,m;
		scanf("%d%d",&n,&m);
		int i;
		for(i=1;i<=n;i++)
		{
			scanf("%d%d",&tr[i].p[0],&tr[i].y);
			tr[i].p[1]=tr[i].p[0]+tr[i].y;
			tr[i].p[2]=tr[i].p[0]-tr[i].y;
		}
		int rt=build(1,n,0);
		printf("Case #%d:\n",k);
		int x,y,d,w;
		for(i=1;i<=m;i++)
		{
			scanf("%d%d%d%d",&x,&y,&d,&w);
			int len=d/2;
			int x11=x-len,x12=y;
			int x21=x-w/2,x22=y+len-w/2;
			int x31=x+w/2,x32=y+len-w/2;
			int x41=x-w/2,x42=y-len+w/2;
			int x51=x+w/2,x52=y-len+w/2;
			int x61=x+len,x62=y;
			//printf("%d %d %d %d %d %d %d %d %d %d %d %d\n",x11,x12,x21,x22,x31,x32,x41,x42,x51,x52,x61,x62);
			//printf("%d %d %d %d %d %d\n",x11,x41+x42,x21-x22,x21,x21+x22,x41-x42);
			if(w!=0)
				printf("%d\n",ask(rt,x11,x41+x42,x21-x22,x21,x21+x22,x41-x42,0)+ask(rt,x31,x51+x52,x31-x32,x61,x31+x32,x51-x52,0));
			else
				printf("%d\n",ask(rt,x11,x41+x42,x21-x22,x61,x21+x22,x41-x42,0));
		}
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值