计蒜客 直线的交点(计算几何 + 逆序对)
题目链接 直线的交点
两条直线的交点如果落在两个平板之内的话
假设这两条直线和两条平板的交点横坐标分别为 $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; }