hdu5862Counting Intersections(树状数组)

来源:互联网 发布:淘宝货到付款付款方式 编辑:程序博客网 时间:2024/05/19 18:16

题目链接:

http://acm.split.hdu.edu.cn/showproblem.php?pid=5862

题目大意:

给一些与坐标轴平行的线段,问有多少个交点。题目保证线段不会有重合的端点。

范围:

n<=100000。

思路:

根据题目的要求,我们可以知道交点一定是横线和竖线产生的。我们可以假设有一条扫描线从左往右扫过去。所以我们对于横线来说,遇到一个横线的左端点,就将他的y进行++操作,遇到右端点,就进行y--操作。如果遇到竖线,就对竖线[y1,y2]区间内进行统计。这两个操作可以利用树状数组维护完成。

为了保证上述操作的正确性,我们需要将坐标按x轴从小到大进行排序。注意当竖线和横线端点在同一个x的位置时,要保证左端点先加上去,然后统计,最后再将右端点减去。

这里我们可以利用一个flag标记,将左端点置为1,竖线置为0,右端点置为-1。

代码:

#include<stdio.h>#include<string.h>#include<algorithm>#define ll __int64using namespace std;struct node{    int x,y,idx,flag,ff;}p[200005];int n,m,a[200005];ll  d[200005];pair<int,int>pp[200005];bool cmp(node a,node b){    if(a.x==b.x){        return a.flag>b.flag;    }    return a.x<b.x;}int lowbit(int x){    return x&(-x);}void update(int x,int z,int n){    while(x<=n){        d[x]+=z;        x+=lowbit(x);    }}ll getsum(int x){    ll ans=0;    while(x){        ans+=d[x];        x-=lowbit(x);    }    return ans;}int main(){    int i,j,x1,y1,x2,y2;    int T;    scanf("%d",&T);    while(T--){        memset(a,0,sizeof(a));        memset(d,0,sizeof(d));        scanf("%d",&n);        int tt=0;        for(i=1;i<=n;i++){            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);            if(x1>x2){                int tmp=x1;                x1=x2;                x2=tmp;                tmp=y1;                y1=y2;                y2=tmp;            }            if(y1>y2){                int tmp=x1;                x1=x2;                x2=tmp;                tmp=y1;                y1=y2;                y2=tmp;            }                p[(i-1)*2+1].x=x1;                p[(i-1)*2+1].y=y1;                p[(i-1)*2+2].x=x2;                p[(i-1)*2+2].y=y2;                p[(i-1)*2+1].ff=p[(i-1)*2+1].ff=0;                if(x1==x2)                {                     p[(i-1)*2+1].flag=p[(i-1)*2+2].flag=0;                     p[(i-1)*2+1].ff=1;                     p[(i-1)*2+2].ff=0;                }                else if(y1==y2)                {                    p[(i-1)*2+1].flag=1;                    p[(i-1)*2+2].flag=-1;                }            a[++tt]=p[(i-1)*2+1].y;            a[++tt]=p[(i-1)*2+2].y;        }        sort(a+1,a+1+tt);        int xx=0;        int siz=unique(a+1,a+1+tt)-a-1;        for(i=1;i<=n;i++){            p[2*i-1].y=lower_bound(a+1,a+1+siz,p[2*i-1].y)-a;            p[2*i].y=lower_bound(a+1,a+1+siz,p[2*i].y)-a;            if(p[2*i-1].x==p[2*i].x){                    pp[++xx]=make_pair(p[2*i-1].y,p[2*i].y);                    p[2*i-1].ff=xx;            }        }        sort(p+1,p+1+2*n,cmp);        ll ans=0;        for(i=1;i<=2*n;i++){            if(p[i].flag!=0){                update(p[i].y,p[i].flag,2*n);            }            else {                    if(p[i].ff){                            int t=p[i].ff;                         ans+=getsum(pp[t].second)-getsum(pp[t].first-1);                    }            }        }        printf("%I64d\n",ans);    }}/*240 0 4 04 0 4 24 -1 4 14 2 5 230 0 2 02 1 2 22 0 2 2*/


0 0