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

题目: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 100050

using 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;
}



发布了59 篇原创文章 · 获赞 3 · 访问量 4万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章