ZOJ 3157 逆序对

来源:互联网 发布:工控网络拓扑图 编辑:程序博客网 时间:2024/06/02 02:54

刚看到这道题时,第一感觉是双重循环,求出所有的交点的横坐标,然后判断是不是在所给范围内。

毫无疑问,结果肯定超时。但换个角度想一下,转化为zoj3129的japan那道题,即是求逆序对的个数。

接下来就和3129一样了。。。

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<float.h>
#define N 10005

struct node{
    double first;
 double second; 
}f[N];

double s[N],t[N];
double a[N][4];
int i,j,k,m,n;
double l,r;
int  ans;

int cmp( const void *a , const void *b )
{
    struct node *c = (struct node *)a;
    struct node *d = (struct node *)b;
    if (fabs(c->first - d->first)<0.0000001)   // 即是不相等
        return c->second > d->second ? 1 : -1 ;
    return c->first > d->first ? 1 : -1 ;
}

void merge(int x,int z,int y)
{
 int n1,n2;
    n1=z-x+1; n2=y-z;
    i=0;j=0;
    for (k=x;k<=z;k++)
        s[i++]=f[k].second;
    s[n1]=DBL_MAX;
    for (k=z+1;k<=y;k++)
        t[j++]=f[k].second;
    t[n2]=DBL_MAX;
    i=0; j=0;
    for(k=x;k<=y;k++){
        if (s[i]>t[j]){
            ans+=(n1-i);
            f[k].second=t[j++];
        }
        else
            f[k].second=s[i++];
    }
}
void merge_sort(int x, int y)
{
 int z;
    if(x<y){
        z=(x+y)/2;
  merge_sort(x, z);
        merge_sort(z+1, y);
        merge(x,z,y);
 }
}

int main()
{
    while(scanf("%d",&n)!=EOF)
    {       
        for(i=0;i<n;i++)
            for (j=0;j<4;j++)
                scanf("%lf", &a[i][j]);   
        scanf("%lf%lf", &l,&r);
        for(i=0;i<n;i++){
            f[i].first=((l-a[i][0])*(a[i][3]-a[i][1])/(a[i][2]-a[i][0]))+a[i][1];   // 平行于y轴的直线x=l与两点确定的直线的交点的纵坐标
            f[i].second=((r-a[i][0])*(a[i][3]-a[i][1])/(a[i][2]-a[i][0]))+a[i][1];   // 平行于y轴的直线x=l与两点确定的直线的交点的纵坐标
        }
        qsort(f,n,sizeof(f[0]),cmp);
        ans=0;
        merge_sort(0,n-1);   
        printf("%d\n",ans);                      
    }
    return 0;
}

原创粉丝点击