hdu_5862_Counting Intersections(扫描线)

时间:2023-12-27 23:22:01

题目链接:hdu_5862_Counting Intersections

题意:

给你与坐标轴平行的线段,问你交点数

题解:

实质就是扫描线,这里我用树状数组来记录,所有线段按X坐标排序,遇到横线段的左端点就对应y坐标+1,遇到右端点,就对应y坐标-1,遇到竖线段,就询问对应的区间段

 #include<bits/stdc++.h>
#define F(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
typedef long long ll; const int N=1e5+;
int sum[N*],n,t,nn,has[N*],cnt,x1,x2,y1,y2,ed,hed; struct seg{
int x,l,r,op;
bool operator<(const seg &b)const{return x<b.x||(x==b.x&&op<b.op);}
}s[N*]; inline void add(int x,int c){while(x<=n)sum[x]+=c,x+=x&-x;}
inline int ask(int x){int an=;while(x)an+=sum[x],x-=x&-x;return an;} inline int getid(int x){return lower_bound(has+,has+cnt+,x)-has;} int main(){
scanf("%d",&t);
while(t--)
{
scanf("%d",&nn),ed=hed=;
memset(sum,,sizeof(sum));
F(i,,nn)
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
has[++hed]=x1,has[++hed]=x2,has[++hed]=y1,has[++hed]=y2;
if(x1==x2)s[++ed].x=x1,s[ed].op=,s[ed].l=min(y1,y2),s[ed].r=max(y2,y1);
else{
s[++ed].x=min(x1,x2),s[ed].op=,s[ed].l=y1,s[ed].r=y1;
s[++ed].x=max(x1,x2),s[ed].op=,s[ed].l=y2,s[ed].r=y2;
}
}
sort(has+,has++hed),cnt=unique(has+,has++hed)-has,n=hed;
F(i,,ed)s[i].x=getid(s[i].x),s[i].l=getid(s[i].l),s[i].r=getid(s[i].r);
sort(s+,s++ed);
ll ans=;
F(i,,ed)if(s[i].op==)add(s[i].l,);
else if(s[i].op==)ans+=ask(s[i].r)-ask(s[i].l-);
else add(s[i].r,-);
printf("%lld\n",ans);
}
return ;
}