zoukankan      html  css  js  c++  java
  • 计蒜客NOIP模拟赛D2T2 直线的交点

    伦伦刚刚在高中学习了解析几何,学会了计算两条直线的交点。这天,老师给她布置了一道作业。在平面上有 nnn 条直线,他们之间有若干交点。给定一对平板(两条平行的直线),问这有多少对直线,他们的交点在这一对平板之间(注意 (i, j) 和 (j, i) 只算一对)。

    输入格式

    第一行三个整数 k,a,b 表示平板的两条平行直线的方程为 y=kx+ay=kx+b,保证 a<b

    第二行一个整数 n

    接下来 n行每行两个整数 ki,bii​​,bi​​ 表示第 iii 条直线的方程 y=kix+biy=k_ix+b_iy=ki​​x+bi​​。

    输出格式

    一个整数,表示有多少对直线,他们的交点在平板之间。

    数据范围与约定

    对于 30%的数据,n≤5000

    对于 100%的数据,n≤100000

    为了简单起见,输入数据保证,没有直线和平板平行,没有两条直线的交点在平板上。

    样例解释

    只有 y=−x+10这条直线和 y=x,y=2x,y=−2x 这三条直线的交点在区域内。

    样例输入

    0 3 50
    5
    1 0
    2 0
    -1 0
    -2 0
    -1 10

    样例输出

    3
    我们要用到以下观察,若两条直线的交点在平板内部。
    则他们与下方平板和上方平板的交点横坐标大小关系相反。
    这表明,如果将所有直线按照他们与下方平板的交点的横坐标排序,
    将他们上方平板交点的横坐标作为关键字。
    则平板内交点个数等于在排序后的序列中关于关键字的逆序对个数。
    于是用归并排序来计算逆序对个数即可
     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 using namespace std;
     6 struct Line
     7 {
     8     double x1,x2;
     9 }line[100001],t[100001];
    10 int n;
    11 double k1,a1,b1;
    12 double k,b;
    13 long long ans;
    14 bool cmp(Line a,Line b)
    15 {
    16     return a.x1<b.x1;
    17 }
    18 void partition(int l,int r)
    19 {
    20     if (l>=r)
    21         return;
    22     int mid=(l+r)/2;
    23     partition(l,mid);
    24     partition(mid+1,r);
    25     int i=l,j=mid+1,k=l;
    26     while(i<=mid&&j<=r)
    27     {
    28         if(line[i].x2>line[j].x2)
    29         {
    30             ans=(ans+mid-i+1);
    31             t[k]=line[j];
    32             k++;
    33             j++;
    34         }
    35         else
    36         {
    37             t[k]=line[i];
    38             k++;
    39             i++;
    40         }
    41     }
    42     while(i<=mid)
    43     {
    44         t[k]=line[i];
    45         k++;
    46         i++;
    47     }
    48     while(j<=r)
    49     {
    50         t[k]=line[j];
    51         k++;
    52         j++;
    53     }
    54     for(i=l; i<=r; i++)
    55         line[i]=t[i];
    56 }
    57 int main()
    58 {int i;
    59     cin>>k1>>a1>>b1;
    60  cin>>n;
    61     for (i=1;i<=n;i++)
    62     {
    63         scanf("%lf%lf",&k,&b);
    64         line[i].x1=(b1-b)/(k-k1);
    65         line[i].x2=(a1-b)/(k-k1);
    66     }
    67     sort(line+1,line+n+1,cmp);
    68     partition(1,n);
    69     cout<<ans;
    70 }
  • 相关阅读:
    如何制作动态层分组报表
    填报表之数据留痕
    填报表中也可以添加 html 事件
    填报脚本之轻松搞定复杂表的数据入库
    在报表中录入数据时如何实现行列转换
    如何在报表中绘制 SVG 统计图
    如何用报表工具实现树状层级结构的填报表
    6.JAVA_SE复习(集合)
    JAVA_SE复习(多线程)
    数据库基本概念
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/7536617.html
Copyright © 2011-2022 走看看