欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

DTOJ3302 星座

程序员文章站 2024-01-31 08:13:34
...

题目

题目描述

为了探索我们头顶那美丽的星空,伟大的C学给了我们一张星图,这张星图可以看做一个平面,其中包含了nn颗星星,每颗星星可以用平面上的一个点来表示,C学告诉我们这张星图中包含着多种神奇的αβγ\alpha - \beta - \gamma星座,这些星座在平面内构成了很多平行四边形,它们的都有一组边长为γ\gamma的对边平行于xx轴,且另一组对边平行于一斜率为βα\frac{\beta}{\alpha}的直线,现在C学给了我们若干组询问,每组询问包含33个整数α,β,γ\alpha,\beta,\gamma,对于每组询问请你求出xx轴上方和下方中αβγ\alpha - \beta - \gamma星座的个数 (平行四边形不能与xx轴有相交的部分)

输入格式

1122个正整数n,mn,m表示星星的个数和询问的个数(4n100,000,1m10)(4 \leqslant n \leqslant 100,000,1 \leqslant m \leqslant 10)
2n+12 \sim n+1行每行22个整数x,yx,y表示每颗星星的横纵坐标(1,000x,y1,000)(-1,000 \leqslant x,y \leqslant 1,000)(数据保证不会有两颗星星在同一个位置)
n+2n+m+1n+2 \sim n+m+1行每行33个整数α,β,γ(1α2,000,2,000β2,000,1γ2,000)\alpha,\beta,\gamma(1 \leqslant \alpha \leqslant 2,000,-2,000 \leqslant \beta \leqslant 2,000,1 \leqslant \gamma \leqslant 2,000)(当β=0\beta=0时,表示一条平行于 y轴的直线)

输出格式

输出共mm
每行两个整数,表示xx轴上方满足条件星座个数和xx轴下方满足条件星座个数

样例

样例输入

8 1
1 1
2 1
1 2
2 2
1 -1
2 -1
1 -2
2 -2
1 0 1

样例输出

1 1

题解

看看这个坐标这么小,它不香吗?
我们用vx,yv_{x,y}表示(x,y)(x,y)有没有点
算出有几条边平行xx轴,然后每条边选择左边那个点
算出斜率投影到xx轴上得到一个坐标,这个坐标相同的两条边可以组合成一个平行四边形(就是横截距相同而且斜率相同的直线只有一条)
附上代码:

#include<algorithm>
#include<cstdio>
using namespace std;
int n,m,len1,len2,ans1,ans2,x[100010],y[100010],v[2010][2010];
double eps=1e-7,d1[100010],d2[100010];
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) scanf("%d%d",&x[i],&y[i]),v[x[i]+1000][y[i]+1000]=1;
	for(int i=1,a,b,c,s;i<=m;i++){
		ans1=ans2=len1=len2=s=0;
		scanf("%d%d%d",&a,&b,&c);
		for(int i=1;i<=n;i++) if(x[i]+c<=1000&&v[x[i]+1000+c][y[i]+1000]){
    		if(y[i]>0){
				d1[++len1]=x[i];
				if(b) d1[len1]-=1.0*a*y[i]/b;
			}
			else{
				d2[++len2]=x[i];
				if(b) d2[len2]-=1.0*a*y[i]/b;
			}
		}
		sort(d1+1,d1+1+len1),sort(d2+1,d2+1+len2);
		for(int i=2;i<=len1;++i)
			if(d1[i]-d1[i-1]<=eps) ++s;
			else ans1+=s*(s+1)/2,s=0;
		ans1+=s*(s+1)/2,s=0;
		for(int i=2;i<=len2;++i)
			if(d2[i]-d2[i-1]<=eps) ++s;
			else ans2+=s*(s+1)/2,s=0;
		printf("%d %d\n",ans1,ans2+s*(s+1)/2);
	}
}