樹狀數組+離散化(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萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章