题意:
给出 一个区间 ( l r),给出 n条直线,问这些直线有多少交点在区间内
思路:
区间的两个端点作为两边x和y。求出直线在两个端点的值。先按照Y升序排序,给它编号,然后按照x升序排序,相等则按照y升序。由于已经按照x升序排序,每读到一条边,只需统计当期有多少y比他大,就有多少交点。
注意和y轴平行的那些直线!!!
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#pragma comment(linker, "/STACK:102400000,102400000")
typedef long long LL;
const int INF = 0x3f3f3f3f;
const int maxn = 50000+5;
using namespace std;
const double eps = 1e-8;
int n, C[maxn];
double s,t;
struct Line{
double x,y;
int yid;
}L[maxn];
bool cmpy(const Line& a, const Line& b){
return a.y < b.y;
}
bool cmp(const Line& a, const Line& b){
if(fabs(a.x-b.x) > eps) return a.x < b.x;
return a.y < b.y;
}
inline int lowbit(int x){return x & -x;}
void add(int x, int v){for(int i = x; i <= n; i+= lowbit(i)) C[i]+= v;}
int sum(int x){
int s = 0;
for(int i = x; i > 0; i-= lowbit(i)) s+= C[i];
return s;
}
int main()
{
freopen("in.txt","r",stdin);
double x1,y1,x2,y2;
while(scanf("%d",&n) == 1){
memset(C, 0, sizeof(C));
scanf("%lf%lf",&s,&t);
int vertical = 0, cnt = 0;
for(int i = 1; i <= n; ++i){
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
if(fabs(x1-x2) <= eps){ // 和 y轴 平行
if(x1 > s&&x1 < t) ++vertical;
continue;
}
double k=(y2-y1)/(x2-x1);
double b=y1-k*x1;
L[++cnt].x = k*s + b;
L[cnt].y = k*t + b;
}
sort(L+1, L+cnt+1, cmpy);
for(int i = 1; i <= cnt; ++i) L[i].yid = i;
sort(L+1, L+cnt+1, cmp);
//for(int i = 1; i <= n; ++i) printf("%d\n",L[i].yid);
LL ans = 0;
for(int i = 1; i <= cnt; ++i){
int b = L[i].yid;
add(b, 1);
ans+= i - sum(b);
//printf("%d, ans = %d\n", sum(b),ans);
}
printf("%lld\n", ans + vertical*cnt);
}
fclose(stdin);
return 0;
}