多校训练10&&HDU5862 Counting Intersections

来源:互联网 发布:华东医院数据库 编辑:程序博客网 时间:2024/05/22 02:21

【题意】真水的题。。不知道我们队干了什么,卡在A题这个水题几个小时,太悲哀了。

【解题方法】这不好说,去偷一份我同学的解题方法吧,思路大概都是这样,扫描线的基础题了,BIT维护信息,扫描线扫过去就完了。

因为题目已经说明所有的线段都是平行于坐标轴的

那么,线段无外乎两种:①平行于x轴;②平行于y轴


那交点必定只有竖向与横向的线段才会产生

另外,此题数据规模显然是不允许我们进行O(n^2)的暴力求解

那我们可以将横向的线段与竖向线段分开处理

对于横向的线段,我们只保留端点

再按x从小到大排序,x相等的情况下,左端点优先于右端点

而竖向的线段同样按x从小到大排序,但是不拆分成两个端点,而是保留整条线段

然后枚举竖向线段,将小于该竖向线段横坐标的所有点进行处理

若点为左端点,则在其对应的值处的树状数组做+1操作,若为右端点,则做-1操作

这保证了对于第i条竖向线段,当前树状数组中记录了横坐标横跨该竖向线段的线段数量


【AC 代码】


#include <bits/stdc++.h>using namespace std;const int maxn = 500010;typedef long long LL;struct bit{    LL c[maxn];int n;    void init(int _n){        memset(c,0,sizeof(c));        n=_n;    }    void add(int i,int v){        while(i<=n){            c[i]+=v;            i+=i&-i;        }    }    int getans(int i){        int ans=0;        while(i>0){            ans+=c[i];            i-=i&-i;        }        return ans;    }}BIT;struct node1{    int x1,y1,x2,y2;}seg[maxn],q[maxn];struct node2{    int x,y,type;}p[maxn];bool cmp1(node2 a,node2 b){    if(a.x!=b.x) return a.x<b.x;    return a.type<b.type;}bool cmp2(node1 a,node1 b){    return a.x1<b.x1;}vector<int>xs;int main(){    int T,n;    scanf("%d",&T);    while(T--){        scanf("%d",&n);        LL ans=0;        BIT.init(maxn);        xs.clear();        for(int i=1; i<=n; i++){            scanf("%d%d%d%d",&q[i].x1,&q[i].y1,&q[i].x2,&q[i].y2);            if(q[i].x1>q[i].x2||q[i].y1>q[i].y2){                swap(q[i].x1,q[i].x2);                swap(q[i].y1,q[i].y2);            }            xs.push_back(q[i].x1);            xs.push_back(q[i].y1);            xs.push_back(q[i].x2);            xs.push_back(q[i].y2);        }        sort(xs.begin(),xs.end());        xs.resize(unique(xs.begin(),xs.end())-xs.begin());        int k1=0,k2=0;        for(int i=1; i<=n; i++){            int x1=lower_bound(xs.begin(),xs.end(),q[i].x1)-xs.begin()+1;            int y1=lower_bound(xs.begin(),xs.end(),q[i].y1)-xs.begin()+1;            int x2=lower_bound(xs.begin(),xs.end(),q[i].x2)-xs.begin()+1;            int y2=lower_bound(xs.begin(),xs.end(),q[i].y2)-xs.begin()+1;            if(y1==y2){                p[++k1].x=x1,p[k1].y=y1,p[k1].type=0;                p[++k1].x=x2,p[k1].y=y2,p[k1].type=1;            }else{                seg[++k2]=node1{x1,y1,x2,y2};            }        }        sort(p+1,p+k1+1,cmp1);        sort(seg+1,seg+k2+1,cmp2);        //扫描线段        for(int i=1,j=1; i<=k2; i++){            while(j<=k1&&(p[j].x<seg[i].x1||(p[j].x==seg[i].x1&&p[j].type==0))){                if(p[j].type==0) BIT.add(p[j].y,1);                else BIT.add(p[j].y,-1);                j++;            }            ans+=BIT.getans(seg[i].y2)-BIT.getans(seg[i].y1-1);        }        printf("%I64d\n",ans);    }    return 0;}


0 0
原创粉丝点击