• 暑假集训Day3 G(树状数组扫描线)


    题目链接在本地,题目大意就是给了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 }
  • 相关阅读:
    jquery获取当前时间比较日期
    php获取时间计算时间差
    计数查询统计
    jQuery选取所有复选框被选中的值并用Ajax异步提交数据
    在java中实现对access数据库的远程访问
    sublime快捷键
    局部变量和成员变量的区别
    常见的几种数组排序方法
    JVM的内存划分
    Java函数
  • 原文地址:https://www.cnblogs.com/keximeiruguo/p/16456090.html
Copyright © 2020-2023  润新知