树状数组+离散化(hdu 5862)

来源:互联网 发布:河北网络电视台 - 百度 编辑:程序博客网 时间:2024/06/06 14:11

题目:hdu 5862

题意:给定几个线段,求有多少个线段的交点,输入解释:第一行表示测试数据,第二行表示有多少条线段,第三行开始是每个线段的两点坐标

题解:树状数组+离散化(Y坐标太大,要压缩存储空间,采用离散化),先用map对y坐标进行离散化,再将与x轴平行的线段拆成两个点,一个是记录起点x坐标,一个记录末点x坐标+1(这样就可保证末点相交被记录进去,方便),与y轴平行的只要记录x坐标和两个y坐标即可,当成一个点,在将所有点以x坐标从小到大进行排列,排除掉了x坐标,就只要考虑y坐标即可,这样树状数组就可进行维护了,在树状数组中以Y坐标为高度,凡是高度在此中间的一定有交点,当然也要有个变量记录该点对应的线段是从与x轴平行的提取出来的还是y轴,具体见下代码

代码:

include<iostream>#include<cstdio>#include<cstring>#include<map>#include<algorithm>#include<string>#define MAX 100050using namespace std;typedef struct{    int kind,x,y,y2;}Segment;Segment s[MAX*2];int Y[MAX*2];int c[MAX*2];int num;int ynum;int mxan;map<int,int> mp;void init(){    num=0;memset(c,0,sizeof(c));ynum=0;mp.clear();mxan=MAX*2;}void addSegment(int kind,int x,int y,int y2){    s[num].kind=kind;s[num].x=x;s[num].y=y;s[num].y2=y2;    num++;}bool compareY(int y1,int y2){    return y1<y2;}bool compareX(Segment z1,Segment z2)//以x坐标进行排序,当坐标相等时,要保证从平行x轴提取的点先进行考虑{    if(z1.x==z2.x)    {        return z1.kind<z2.kind;    }    else    {        return z1.x<z2.x;    }}int lowbit(int x){    return x&(-x);}void add(int i,int v){    while(i<=mxan)    {        c[i]+=v;        i+=lowbit(i);    }}int sum(int i){    int ans=0;    while(i>0)    {        ans+=c[i];        i-=lowbit(i);    }    return ans;}int main(){    int t;    scanf("%d",&t);    while(t--)    {        int n;        init();        scanf("%d",&n);        for(int i=0;i<n;i++)        {            int x,y,x1,y1;            scanf("%d %d %d %d",&x,&y,&x1,&y1);            if(x==x1)            {                if(y1>y) swap(y,y1);                addSegment(1,x,y,y1);                Y[ynum++]=y;                Y[ynum++]=y1;            }            else            {                if(x>x1) swap(x,x1);                addSegment(0,x,y,1);                addSegment(0,x1+1,y,-1);                Y[ynum++]=y;            }        }        sort(Y,Y+ynum,compareY);        int count1=1;        for(int i=0;i<ynum;i++)//离散化        {            if(!mp[Y[i]]) {mp[Y[i]]=count1++;}        }        mxan=count1+1;        sort(s,s+num,compareX);        long long sum2=0;        for(int i=0;i<num;i++)        {            if(s[i].kind==0)            {                add(mp[s[i].y],s[i].y2);            }            else            {                sum2+=sum(mp[s[i].y])-sum(mp[s[i].y2]-1);            }        }        printf("%lld\n",sum2);    }    return 0;}



0 0