• 假几何真逆序数 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 }
  • 相关阅读:
    Android开发学习之路--Content Provider之初体验
    [NOI2005] 维修数列
    递归算法对完全二叉树的前序遍历
    非递归算法对完全二叉树的前序遍历
    java中的多态
    poj1088滑雪
    在网页中插入flash
    如何采用批处理文件安装一个.dll文件,并且注册
    结构体指针和数组理解
    完全二叉树
  • 原文地址:https://www.cnblogs.com/oscar-cnblogs/p/7615527.html
Copyright © 2020-2023  润新知