计蒜客 直线的交点(计算几何 + 逆序对)

题目链接 直线的交点

两条直线的交点如果落在两个平板之内的话

假设这两条直线和两条平板的交点横坐标分别为  $x1, x2, X1, X2$

那么有$(x2 - x1)(X2 - X1) < 0$

于是这就转化成了一个经典问题

我们求出所有直线和平板的两个交点的横坐标,按其中一个平板的横坐标排序,

然后对另一个平板的横坐标求逆序对即可。

#include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define dec(i, a, b)	for (int i(a); i >= (b); --i)

typedef long long LL;

const int N = 1e5 + 10;

double k, b1, b2;
double a[N], b[N];
int f[N], t[N], n;
LL  ans = 0;

struct node{
	double x, y;
	int id;
	friend bool operator < (const node &a, const node &b){
		return a.x < b.x;
	}
} c[N];


bool cmp(const node &a, const node &b){ return a.y < b.y; }
double calc(double k1, double b1, double k2, double b2){ return (b2 - b1) / (k1 - k2);}

void update(int x){ for (; x <= n; x += x & -x) ++t[x];}
int query(int x){ int ret(0); for (; x; x -= x & -x) ret += t[x]; return ret;}


int main(){

	scanf("%lf%lf%lf", &k, &b1, &b2);
	scanf("%d", &n);

	rep(i, 1, n) scanf("%lf%lf", a + i, b + i);
	rep(i, 1, n) c[i].x = calc(a[i], b[i], k, b1);
	rep(i, 1, n) c[i].y = calc(a[i], b[i], k, b2);

	sort(c + 1, c + n + 1);
	rep(i, 1, n) c[i].id = i;
	sort(c + 1, c + n + 1, cmp);
	rep(i, 1, n) f[c[i].id] = i;

	dec(i, n, 1) ans += (LL)query(f[i] - 1), update(f[i]);

	printf("%lld\n", ans);
	return 0;
}

 

posted @ 2017-09-17 10:59  cxhscst2  阅读(287)  评论(0编辑  收藏  举报