题目链接在本地,题目大意就是给了n个矩形,问是否存在两个矩形,它们的边有相交(注:回字形嵌套的边没有相交)
依旧是非常经典的扫描线问题,不过传统的扫描线是用来求矩形面积之和的,但是对于这道题,我们需要判断给定一个区间,其上是否存在线段,存在几个线段,因此不能用传统的方法去想。猫猫想了一个很有趣的方法,类似于差分约束,但又完全不同,即如果插入一条线段,则在线段的左端点加一,右端点也加一,判断一个区间上是否完整有一条线段的方法就是用树状数组查询两个端点,然后求差,如果差为0则没有完全包含一条线段。这个思想非常值得学习,判断一个区间内是否有线段。
另一个需要学习的就是离散化和stl二分的方法,在扫描线的问题中极其常见。
1 #include "bits/stdc++.h" 2 using namespace std; 3 const int MAX=2e5+5; 4 int n,c[MAX<<1],bas[MAX<<1],cnt,m; 5 bool flag; 6 struct Edge{ 7 int x,y,h,tg; 8 bool operator < (const Edge &tt) const { 9 return h<tt.h; 10 } 11 }edge[MAX]; 12 void update(int x,int y){ for (;x<=m;x+=(x&-x)) c[x]+=y; } 13 int search(int x){int an=0;for (;x>0;x-=(x&-x)) an+=c[x]; return an;} 14 int main(){ 15 // freopen ("g.in","r",stdin); 16 // freopen ("g.out","w",stdout); 17 int i,j,x1,y1,x22,y2,ll,rr; 18 scanf("%d",&n); 19 cnt=m=0; flag=true; 20 for (i=1;i<=n;i++){ 21 scanf("%d%d%d%d",&x1,&y1,&x22,&y2); 22 cnt++; 23 edge[cnt].x=x1,edge[cnt].y=x22,edge[cnt].h=y1,edge[cnt].tg=1; 24 cnt++; 25 edge[cnt].x=x1,edge[cnt].y=x22,edge[cnt].h=y2,edge[cnt].tg=-1; 26 bas[++m]=x1,bas[++m]=x22,bas[++m]=y1,bas[++m]=y2; 27 } 28 sort(edge+1,edge+cnt+1); 29 sort(bas+1,bas+m+1); 30 m=unique(bas+1,bas+m+1)-(bas+1); 31 memset(c,0,sizeof(c)); 32 for (i=1;i<=cnt;i++){ 33 ll=lower_bound(bas+1,bas+m+1,edge[i].x)-bas; 34 rr=lower_bound(bas+1,bas+m+1,edge[i].y)-bas; 35 if (edge[i].tg==1){ 36 if (search(ll)!=search(rr)){ 37 flag=false; 38 break; 39 } 40 update(ll,edge[i].tg); 41 update(rr,edge[i].tg); 42 } 43 else{ 44 update(ll,edge[i].tg); 45 update(rr,edge[i].tg); 46 if (search(ll)!=search(rr)){ 47 flag=false; 48 break; 49 } 50 } 51 } 52 if (flag) printf("0"); 53 else printf("1"); 54 return 0; 55 }