C小加

厚德 博学 求真 至善 The bright moon and breeze
posts - 145, comments - 195, trackbacks - 0, articles - 0
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

NYOJ 475 Doctor's order (逆序数)

Posted on 2012-03-19 13:43 C小加 阅读(281) 评论(0)  编辑 收藏 引用 所属分类: 解题报告

大意:两个垂直于x轴的直线lxrx围成的区域。有n条直线穿过这片区域,每条直线yi=kxi+b,给出kb。求直线把这个区域分成了几个部分。三条直线不会交于一点(包括:两个垂直于x轴的直线)。

画图可以找出一种关系,分成的区域数=交点数+线段数+1;对左端点从大到小排序,然后对右端点求逆序数,逆序数就是交点数,线段数已知,空间数就出来了。



#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int MAXM=30004;
const int INF=0x7fffffff-1;
typedef struct
{
    int y1,y2;
}Line;
Line line[MAXM];
int temp1[MAXM/2+1];
int temp2[MAXM/2+1];
int cnt;
bool cmp(Line l1,Line l2)
{
    return l1.y1>l2.y1;
}
void merge(int start,int mid,int end)
{
    int n1,n2;
    n1=mid-start+1;
    n2=end-mid;
    for(int i=0;i<n1;i++)
    temp1[i]=line[start+i].y2;
    for(int i=0;i<n2;i++)
    temp2[i]=line[mid+i+1].y2;
    temp1[n1]=-INF;
    temp2[n2]=-INF;
    for(int k=start,i=0,j=0;k<=end;k++)
    {
        if(temp1[i]>=temp2[j])
        {
            line[k].y2=temp1[i];
            i++;
        }
        else
        {
            cnt+=n1-i;//求逆序数
            line[k].y2=temp2[j];
            j++;
        }
    }

}
//归并排序
void mergesort(int start,int end)
{
    if(start>=end) return;
    int mid=(end+start)/2;
    mergesort(start,mid);
    mergesort(mid+1,end);
    merge(start,mid,end);

}

int main()
{
    int lx,rx;
    while(scanf("%d%d",&lx,&rx)!=EOF)
    {
        cnt=0;
        int n,k,b;
        scanf("%d",&n);
        for(int i=0;i<n;i++)
        {
            scanf("%d%d",&k,&b);
            line[i].y1=lx*k+b;
            line[i].y2=rx*k+b;

        }
        sort(line,line+n,cmp);//对左端点从大到小排序
        mergesort(0,n-1);
        printf("%d\n",cnt+n+1);//空间数=交点数+线段数+1

    }
    return 0;
}


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理