假几何真逆序数 NB HDU3465

题意:

有n条直线,问他们两两在横坐标开区间(L,R)之间相交的个数

n=50000,暴力肯定就不用想了,如果在纸上画一画可以发现如果两条直线在(L,R)内相交,那么他们与x= L和x=R的交点序数是相反的

所以我们只需要算与x=L的交点,然后根据这些点排序编个号,在与R相交,根据新的交点排个逆序,根据编号求逆序数即可。

需要注意的一点:两种特殊情况如果不与L,R相交,那么如果再这个区间内,必定所有直线都会与之相交,记录下数量。

另一种情况就是,如果两个直线的交点正巧在x=L和x=R时, 这种情况是不能记录在内的,那么在之前排序的时候与L相交的交点按升序排列

如果交点坐标相同按R交点坐标升序,再根据R的坐标排降序的时候,如果R坐标相同,根据L的坐标排降序,就可以避免这种情况计算在内了。

求逆序数的时候是不会计算在里面的。

求逆序数树状数组即可。

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <iostream>
  4 #include <queue>
  5 #include <vector>
  6 #include <algorithm>
  7 #include <stack>
  8 #include <set>
  9 #include <map>
 10 #include <cmath>
 11 #define pb push_back
 12 #define CLR(a) memset(a, 0, sizeof(a));
 13 #define MEM(a, b) memset(a, b, sizeof(a));
 14 #define fi first
 15 #define se second
 16 
 17 using namespace std;
 18 
 19 typedef long long ll;
 20 
 21 const int MAXN = 50007;
 22 const int MAXV = 207;
 23 const int MAXE = 207;
 24 const int INF = 0x3f3f3f3f;
 25  
 26 int n;
 27 
 28 struct Node
 29 {
 30     double a, b;
 31     int nu;
 32     Node () {}
 33     Node (double a, double b) : a(a), b(b) {}
 34 }node[MAXN];
 35 double L, R;
 36 
 37 bool cmpl(Node n1, Node n2)
 38 {
 39     if (n1.a == n2.a)
 40         return n1.b < n2.b;
 41     else return n1.a < n2.a;
 42 }
 43 bool cmpr(Node n1, Node n2)
 44 {
 45     if (n1.b == n2.b)
 46         return n1.a > n2.a;
 47     else return n1.b > n2.b;
 48 }
 49 int cnt = 0;
 50 int c[MAXN << 1];
 51 int lowbit(int x)
 52 {
 53     return x&(-x);
 54 }
 55 void modify(int x, int data)
 56 {
 57     for (int i = x; i < MAXN; i+= lowbit(i))
 58         c[i] += data;
 59 }
 60 int getsum(int x)
 61 {
 62     int res = 0;
 63     for (int i = x; i > 0; i -= lowbit(i))
 64         res += c[i];
 65     return res;
 66 }
 67 
 68 int main()
 69 {
 70     while (~scanf("%d", &n))
 71     {
 72         CLR(node);
 73         CLR(c);
 74         scanf("%lf%lf", &L, &R);
 75         cnt = 0;
 76         int vrtcl = 0;
 77         for (int i = 0; i < n; i++)
 78         {
 79             double x1, y1, x2, y2;
 80             scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
 81             if (x1 == x2)
 82             {
 83                 if (x1 > L && x1 < R) vrtcl++;
 84                 continue;
 85             }
 86             double k = (y2-y1)/(x2-x1);
 87             double b = y2 - k*x2;
 88             double l = k*L+b, r = k*R+b;
 89             node[cnt++] = Node(l, r);
 90         }
 91         sort(node, node+cnt, cmpl);
 92         for (int i = 0; i < cnt; i++) node[i].nu = i+1;
 93         sort(node, node+cnt, cmpr);
 94         //for (int i = 0; i < cnt; i++) cout << node[i].nu << endl;
 95         int ans = 0;
 96         for (int i = 0; i < cnt; i++)
 97         {
 98             ans += getsum(node[i].nu);
 99             modify(node[i].nu, 1);
100         }
101         ans += cnt*vrtcl;
102         cout << ans << endl;
103     }
104     return 0;
105 }
原文地址:https://www.cnblogs.com/oscar-cnblogs/p/7615527.html