[思路来自已发布的大佬%% 进行了具体的解释]
题目要求交点的个数我们画个图来看一下
那么我们可以发现当我们固定某一点为起点在圆周上进行枚举
两条线有交点的条件是 两条线的端点是插着的
就用上面那个图以圆在X负半轴的交点为起点 黄色和绿色线的端点是插着的 而黄色与红色的没有 所以你就可以发现我刚刚说的是有道理的
所以我们就可以用树状数组(其他你喜欢的也可以)进行维护
之前在通过推道公式求出两个端点的坐标就可以了 (代码中有详细过程)
然后就是化曲为直 我是先将X上下半轴分开 再分别按从小到大和从大到小排
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<cmath>
#define LL long long
using namespace std;
inline void read(LL &x){
x=0;LL f=1;char c=getchar();
while(c>'9'||c<'0'){if(c=='-') f=-1;c=getchar(); }
while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
x*=f;
}
struct node{
double x,y;
LL num;
}e[100050];
LL n;
double a,b,c,d;
inline double Y(double X)
{
return (double)(-a*X-c)*1.0/b;
}
inline LL cmpy(node a,node b)
{
return a.y < b.y;
}
inline LL cmpu(node a,node b)
{
return a.x>b.x;
}
inline LL cmpd(node a,node b)
{
return a.x<b.x;
}
inline LL lowbite(LL k)
{
return k&(-k);
}
LL N;
LL tr[100500];
inline void add(LL pos,LL v)
{
for(LL i=pos;i<=N;i+=lowbite(i))
{
tr[i]+=v;
}
}
inline LL query(LL pos)
{
LL res=0;
for(LL i=pos;i>0;i-=lowbite(i))
{
res+=tr[i];
}
return res;
}
LL v[50010];
int main()
{
read(n);
scanf("%lf",&d);
N=n*2;
LL k=0;
for(LL TT=1;TT<=n;TT++)
{
scanf("%lf",&a);
scanf("%lf",&b);
scanf("%lf",&c);
//ax+by+c=0;
//x*x+y*y=d*d
//y=(-ax-c)/b
//x*x+(ax*ax+2*a*c*x+c*c)/b*b = d*d
//x*x*b*b + a*a*x*x + 2*a*c*x = d*d*b*b - c*c
//(a*a+b*b)*x*x + 2*a*c*x = d*d*b*b - c*c
//(a*a+b*b)*x*x + 2*a*c*x +(c*c - d*d*b*b) = 0
if(a==0)
{
//by+c=0
e[TT*2-1].y = (-c)*1.0/b;
e[TT*2-1].x = sqrt(d*d-e[TT*2-1].y);
e[TT*2-1].num = TT;
e[TT*2].y = (-c)*1.0/b;
e[TT*2].num = TT;
e[TT*2].x = -sqrt(d*d-e[TT*2].y);
if(e[TT*2-1].y < 0) k++;
if(e[TT*2].y < 0) k++;
continue;
}
if(b==0)
{
//ax+c=0
e[TT*2-1].x = (-c)*1.0/a;
e[TT*2-1].y = sqrt(d*d-e[TT*2-1].x);
e[TT*2-1].num = TT;
e[TT*2].x = (-c)*1.0/a;
e[TT*2].y = -sqrt(d*d-e[TT*2].x);
e[TT*2].num = TT;
if(e[TT*2-1].y < 0) k++;
if(e[TT*2].y < 0) k++;
continue;
}
LL A=a*a+b*b;
LL B=2*a*c;
LL C=c*c-d*d*b*b;
LL delta=B*B-4*A*C;
if(delta<=0) continue;
e[TT*2-1].x = (-B+sqrt(delta))*1.0/(2*A);
e[TT*2-1].y = Y(e[TT*2-1].x);
e[TT*2-1].num = TT;
if(e[TT*2-1].y < 0) k++;
e[TT*2].x = (-B-sqrt(delta))*1.0/(2*A);
e[TT*2].y = Y(e[TT*2].x);
e[TT*2].num = TT;
if(e[TT*2].y < 0) k++;
}
stable_sort(e+1,e+1+n*2,cmpy);
// for(LL i=1;i<=N;i++)
// cout<<e[i].x<<" "<<e[i].y <<" " <<e[i].num<<" Y1Y"<<endl;
// cout<<endl;
stable_sort(e+1,e+1+k,cmpd);
// for(LL i=1;i<=N;i++)
// cout<<e[i].x<<" "<<e[i].y <<" " <<e[i].num<<" Y2Y"<<endl;
// cout<<endl;
stable_sort(e+1+k,e+1+n*2,cmpu);
LL ans=0;
for(LL i=1;i<=N;i++)
{
// cout<<e[i].x<<" "<<e[i].y <<" " <<e[i].num<<" YYY"<<endl;
if(e[i].num == 0) continue;
// cout<<v[e[i].num]<<endl;
if(v[e[i].num]==0)
{
v[e[i].num]=i;
add(i,1);
}
else
{
// cout<<query(i)<<" "<<query(v[e[i].num])<<endl;
LL tmp=(query(i)-query(v[e[i].num]));
add(v[e[i].num],-1);
// if(tmp<=0) continue;
ans+=tmp;
}
}
printf("%lld",ans);
return 0;
}
京公网安备 11010502036488号