【HDU5862】Counting Intersections

题意

  有n条线段,且都平行于坐标轴。对于每条线段,给出两个端点的坐标。问一共有多少个线段的交点。

分析

  最最简单的扫描法了。用线段树或者树状数组都可以。

  由题目可知,线段只有两种,要么平行于x轴要么平行于y轴。而交点只能是两个不平行的线段产生的。

  所有我们以一条平行于x轴的线为扫描线,从下向上扫。先把横坐标进行离散化,然后把平行于y轴的线段拆成上下两个端点。当扫到下端点的时候就在它横坐标+1,当扫到上端点的时候,就在它横坐标-1.对于每一条平行于x轴的线,则将左右端点内的值相加。就酱~

  这里一个小细节是,如果是下端点,则先更新,再计算。如果是上端点,则先计算再更新。

  讲真,这个题让我很难受,本来以为很快就能解决的题结果TLE了一晚上,刚刚才发现,是数组开小了(;´༎ຶД༎ຶ`) 

线段树

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <cstring>
 5 #include <cmath>
 6 using namespace std;
 7 typedef long long LL;
 8 const int maxn=100000+100;
 9 struct Point {
10     int j;//1,0,-1
11     int x,h;
12     int l,r;
13     bool operator <(const Point &rhs)const {
14         return h<rhs.h||(h==rhs.h&&j>rhs.j);
15     }
16 }seg[2*maxn];
17 int T,n,x1,y1,x2,y2,sz,sk;
18 LL ans;
19 int v[2*maxn],sumv[8*maxn];
20 int vv,x;
21 void update(int o,int L,int R){
22     if(L==R){
23         sumv[o]+=vv;
24         return ;
25     }
26     int M=L+(R-L)/2;
27     if(x<=M) update(2*o,L,M);
28     if(x>M) update(2*o+1,M+1,R);
29     sumv[o]=sumv[2*o]+sumv[2*o+1];
30     return ;
31 }
32 int ql,qr;
33 int query(int o,int L,int R){
34     if(ql<=L&&qr>=R){
35         return sumv[o];
36     }
37     int res=0;
38     int M=L+(R-L)/2;
39     if(ql<=M)
40         res+=query(2*o,L,M);
41     if(qr>M)
42         res+=query(2*o+1,M+1,R);
43     return res;
44 }
45 int main(){
46     scanf("%d",&T);
47     for(int t=1;t<=T;t++){
48         sz=sk=ans=0;
49         scanf("%d",&n);
50         for(int i=1;i<=n;i++){
51             scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
52             if(x1>x2||y1>y2){
53                 swap(x1,x2);
54                 swap(y1,y2);
55             }
56             if(x1==x2){
57                 seg[++sz].x=x1,seg[sz].h=y1,seg[sz].j=1;
58                 seg[++sz].x=x1,seg[sz].h=y2,seg[sz].j=-1;
59                 v[++sk]=x1;
60             }else if(y1==y2){
61                 seg[++sz].h=y1,seg[sz].l=x1,seg[sz].r=x2,seg[sz].j=0;
62                 v[++sk]=x1,v[++sk]=x2;
63             }
64         }
65         sort(seg+1,seg+1+sz);
66         sort(v+1,v+1+sk);
67         int N=unique(v+1,v+1+sk)-v-1;
68         memset(sumv,0,sizeof(sumv));
69         for(int i=1;i<=sz;i++){
70             if(seg[i].j==0){
71                 ql=lower_bound(v+1,v+1+N,seg[i].l)-v;
72                 qr=lower_bound(v+1,v+1+N,seg[i].r)-v;
73                 ans+=query(1,1,N);
74             }else{
75                 vv=seg[i].j;x=lower_bound(v+1,v+1+N,seg[i].x)-v;
76                 update(1,1,N);
77             }
78         }
79         printf("%lld
",ans);
80     }
81 return 0;
82 }
View Code

  

树状数组

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <cstring>
 4 #include <iostream>
 5 
 6 using namespace std;
 7 
 8 const int maxn=100000+100;
 9 struct Point {
10     int j;//1,0,-1
11     int x,h;
12     int l,r;
13     bool operator <(const Point &rhs)const {
14         return h<rhs.h||(h==rhs.h&&j>rhs.j);
15     }
16 }seg[2*maxn];
17 int T,n,x1,y1,x2,y2,sz,sk,N;
18 long long ans,C[2*maxn];
19 int v[2*maxn];
20 int lowbit(int x){
21     return x&(-x);
22 }
23 void add(int x,int d){
24     while(x<=N){
25         C[x]+=d;
26         x+=lowbit(x);
27     }
28 }
29 long long sum(int x){
30     long long res=0;
31     while(x>0){
32         res+=C[x];
33         x-=lowbit(x);
34     }
35     return res;
36 }
37 int main(){
38     scanf("%d",&T);
39     for(int t=1;t<=T;t++){
40         sz=sk=ans=0;
41         scanf("%d",&n);
42         for(int i=1;i<=n;i++){
43             scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
44             if(x1>x2||y1>y2){
45                 swap(x1,x2);
46                 swap(y1,y2);
47             }
48             if(x1==x2){
49                 seg[++sz].x=x1,seg[sz].h=y1,seg[sz].j=1;
50                 seg[++sz].x=x1,seg[sz].h=y2,seg[sz].j=-1;
51                 v[++sk]=x1;
52             }else if(y1==y2){
53                 seg[++sz].h=y1,seg[sz].l=x1,seg[sz].r=x2,seg[sz].j=0;
54                 v[++sk]=x1,v[++sk]=x2;
55             }
56         }
57         sort(seg+1,seg+1+sz);
58         sort(v+1,v+1+sk);
59         N=unique(v+1,v+1+sk)-v-1;
60 
61         for(int i=1;i<=sz;i++){
62              if(seg[i].j==0){
63                 int l=lower_bound(v+1,v+1+N,seg[i].l)-v;
64                 int r=lower_bound(v+1,v+1+N,seg[i].r)-v;
65               //  cout<<l<<" "<<r<<endl;
66                 ans+=sum(r)-sum(l-1);
67              }
68              else{
69                 int x=lower_bound(v+1,v+1+N,seg[i].x)-v;
70              //   cout<<x<<" "<<seg[i].j<<endl;
71                 add(x,seg[i].j);
72              }
73         }
74         printf("%lld
",ans);
75     }
76 return 0;
77 }
View Code
原文地址:https://www.cnblogs.com/LQLlulu/p/9040342.html