計蒜客 直線的交點(計算幾何 + 逆序對)
阿新 • • 發佈:2017-09-17
clas ret ons oid date pda 所有 efi define
題目鏈接 直線的交點
兩條直線的交點如果落在兩個平板之內的話
假設這兩條直線和兩條平板的交點橫坐標分別為 $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; }
計蒜客 直線的交點(計算幾何 + 逆序對)