zoukankan      html  css  js  c++  java
  • cdoj1341卿学姐与城堡的墙

    地址:http://acm.uestc.edu.cn/#/problem/show/1341

    题目:

    卿学姐与城堡的墙

    Time Limit: 2000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others)
     

    卿学姐终于来到了魔王的城堡,城堡修建的十分壮观。

    即使心中放不下公主,卿学姐还是忍不住驻足观赏这宏伟的建筑。

    卿学姐注意到城堡的墙上有若干直线状的花纹。

    可以将墙看做一个平面,卿学姐想知道有多少种方式任取两个直线,使得这两个直线的交点的横坐标xx满足:uxvu≤x≤v。

    Input

    第一行三个整数N,u,vN,u,v,标明直线有NN条。

    接下来有NN行,每行两个整数k,bk,b,表示这条直线是y=kx+by=kx+b

    1N2000001≤N≤200000

    0|k|10000000000≤|k|≤1000000000

    0|b|10000000000≤|b|≤1000000000

    0|u|10000000000≤|u|≤1000000000

    0|v|10000000000≤|v|≤1000000000

    输入保证uvu≤v,保证没有两条直线是一样的

    Output

    输出一个整数,代表选择的方法数。

    Sample input and output

    Sample InputSample Output
    3 -3 1
    -1 3
    2 2
    1 1
    3

    Hint

    title

    上图是样例的解释,交点是A,B,C

    思路:

    对所有直线进行预处理(只保存和uv的交点)这是很容易想到的,不过一开始不知道有种东西叫逆序对,只想到n*n的算法。。。。。。。

    逆序对的求法有好几种我用的是归并的方法。。

    不过这个题要考虑边界情况,如果按u边界的y排序的话,就需要对u边界上的点特殊处理,其实就是u边界上的点扫一遍就好了,,,

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <cstdio>
     4 #include <cmath>
     5 #include <cstring>
     6 #include <queue>
     7 #include <stack>
     8 #include <map>
     9 #include <vector>
    10 #include <cstdlib>
    11 #include <string>
    12 
    13 #define PI acos((double)-1)
    14 #define E exp(double(1))
    15 using namespace std;
    16 
    17 vector<pair<long long ,long long > >p;
    18 long long  a[200000+5];
    19 long long  temp[200000+5];
    20 long long  cnt=0;//逆序对的个数
    21 double cnm_lg(int n,int m)
    22 {
    23     int i;
    24     double s1=0.0,s2=0.0;
    25     for(i=1;i<=m;i++)
    26         s1 += log(i);
    27     for(i=n-m+1;i<=n;i++)
    28         s2 += log(i);
    29     return s2-s1;
    30 }
    31 long long  cnm_double(int n,int m)
    32 {
    33     if(n<m)
    34         return 0;
    35     if(m > n/2)
    36     m = n-m;
    37     return (long long)exp(cnm_lg(n,m));
    38 }
    39 void merge(int left,int mid,int right)
    40 {
    41     int i=left,j=mid+1,k=0;
    42     while (( i<=mid )&& (j<=right))
    43           if (a[i]<a[j]) temp[k++]=a[i++];
    44           else {
    45               cnt+=mid+1-i;//关键步骤
    46               temp[k++]=a[j++];
    47           }
    48     while (i<=mid) temp[k++]=a[i++];
    49     while (j<=right) temp[k++]=a[j++];
    50     for (i=0,k=left; k<=right;) a[k++]=temp[i++];
    51 }
    52 void mergeSort(int left,int right)
    53 {
    54     if (left<right)
    55     {    int mid=(left+right)/2;
    56          mergeSort(left, mid);
    57          mergeSort(mid+1, right);
    58          merge(left, mid, right);
    59     }
    60 }
    61 int main (void)
    62 {
    63     int n,u,v;
    64     cin>>n>>u>>v;
    65     for(int i=0;i<n;i++)
    66     {
    67         long long k,b;
    68         scanf("%lld%lld",&k,&b);
    69         p.push_back(make_pair(b+u*k,b+v*k));
    70     }
    71     sort(p.begin(),p.end());
    72     p.push_back(make_pair(0,1000000000));
    73     pair<long ,long >temp=p[0];
    74     temp.second=0;
    75     for(int i=1;i<=n;i++)
    76         if(temp.first != p[i].first || i==n)
    77         {
    78             cnt+=cnm_double(i-temp.second,2);
    79             temp.first=p[i].first;temp.second=i;
    80         }
    81     if(u==v)
    82     {
    83         cout<<cnt<<endl;return 0;
    84     }
    85     for(int i=0;i<n;i++)
    86         a[i]=p[i].second;
    87     mergeSort(0,n-1);
    88     cout<<cnt<<endl;
    89     return 0;
    90 }
    View Code
  • 相关阅读:
    AirtestIDE基本功能(二)
    AirtestIDE基本功能(一)
    Pycharm Debug功能详解
    AirtestIDE环境安装
    leetcode-338. 比特位计数
    leetcode-401. 二进制手表
    leetcode-392. 判断子序列
    leetcode-155. 最小栈
    leetcode-111. 二叉树的最小深度
    leetcode-110. 平衡二叉树
  • 原文地址:https://www.cnblogs.com/weeping/p/5456099.html
Copyright © 2011-2022 走看看