題目: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;
}