HDU - 4938 Seeing People 二分查找

题意:给出两种人,第一种人初始位置为(pi,0),出发时间为ti,速度[矢量]为(0,vi),视野范围为wi,也就是说当它在(xi,yi)时,能看见(xi,yi)->(xi+wi,yi)这条水平线段上的人【闭区间】

第二种人,初始位置为(0,pi),出发时间为ti,速度为(vi,0),视野范围为wi,当它在(xi,yi),能看见(xi,yi)->(xi,yi+wi)这段垂直线段上人的【闭区间】

现在问,每个人最后能看到多少个不同的人

样例:第一个人和第二个人在第2s时在(1,2)相遇,所以看到的人数分别是1

(1<=n,v1,v2<=10^5)(T<=10)(1<=ai<=2, 1<=ti,pi,wi<=10^5)

题解:

第一种人新坐标\((pi,-v1*ti)\)

第二种人新坐标\((-v2*tj,pj)\)

对于每个第一种人i找有多少第二种人j

第二种人满足的条件为他到x=pi和x=pi+wi的时间为\((pi+v2*tj)/v2\)\((pi+wi+v2*tj)/v2\)

第一种人到达y=pj的时间为\((pj+v1*ti)/v1\)

所以相遇不等式为\((pi+v2*tj)/v2<=(pj+v1*ti)/v1<=(pi+wi+v2*tj)/v2\)

转化一下中间剩下\(pj-v1*tj\)

\(v1*pi/v2-v1*ti<=pj-v1*tj<=v1*(pi+wi)/v2-v1*ti\)

预处理第二种人的数组\(pj-v1*tj\)

在这个数组中二分一下左端点和右端点看有多少j满足条件

PS:有个小坑,因为推出来的式子中有除法,用整型向下取整的时候可能会有精度问题,我换成了double才过的

代码:

#include<bits/stdc++.h>
using namespace std;

const int N=1e5+10;
int T;
typedef long long ll;
int n,n1,n2,t[2][N],p[2][N],w[2][N],id[2][N],ans[N];
double v1,v2;
vector<ll> v;

int main()
{
	scanf("%d",&T);
	int cas=0;
	while(T--)
	{
		n1=n2=0;
		scanf("%d%lf%lf",&n,&v1,&v2);
		for(int i=1;i<=n;i++)
		{
			int a,x,y,z;scanf("%d%d%d%d",&a,&x,&y,&z);
			if(a==1) t[0][++n1]=x,p[0][n1]=y,w[0][n1]=z,id[0][n1]=i;
			else t[1][++n2]=x,p[1][n2]=y,w[1][n2]=z,id[1][n2]=i;
		}
		printf("Case #%d:\n",++cas);
		v.clear();
		for(int i=1;i<=n2;i++)v.push_back(p[1][i]-1ll*v1*t[1][i]);
		sort(v.begin(),v.end());
		for(int i=1;i<=n1;i++)
		{
			int l=lower_bound(v.begin(),v.end(),1ll*(v1*p[0][i]/v2)-1ll*(v1*t[0][i]))-v.begin();
			int r=upper_bound(v.begin(),v.end(),1ll*(v1*(p[0][i]+w[0][i])/v2)-1ll*(v1*t[0][i]))-v.begin()-1;//cout<<v1*(p[0][i]+w[0][i])/v2-v1*t[0][i]<<endl;
			ans[id[0][i]]=r-l+1;
		}
		v.clear();
		for(int i=1;i<=n1;i++)v.push_back(p[0][i]-1ll*v2*t[0][i]);
		sort(v.begin(),v.end());
		for(int i=1;i<=n2;i++)
		{
			int l=lower_bound(v.begin(),v.end(),1ll*(v2*p[1][i]/v1)-1ll*(v2*t[1][i]))-v.begin();
			int r=upper_bound(v.begin(),v.end(),1ll*(v2*(p[1][i]+w[1][i])/v1)-1ll*(v2*t[1][i]))-v.begin()-1;
			ans[id[1][i]]=r-l+1;
		}
		for(int i=1;i<=n;i++)printf("%d\n",ans[i]);
		memset(ans,0,sizeof(ans));
		memset(t,0,sizeof(t));
		memset(w,0,sizeof(w));
		memset(p,0,sizeof(p));
		memset(id,0,sizeof(id));
	}
	return 0;
}
posted @ 2020-08-26 20:13  JWizard  阅读(159)  评论(0)    收藏  举报