CSU 1292 Rectangles Intersection

  原题链接:http://122.207.68.93/OnlineJudge/problem.php?id=1292

  线段树+扫描线。这道题是典型的矩形面积并问题,乍一看109 * 109 * 10超了long long,但这个无关紧要,其实如果总面积>1018 可以直接判断肯定有相交的面积了,这么一来,就是裸模版题了,贴膜板:

  1 #include "cstdio"
  2 #include "iostream"
  3 #include "algorithm"
  4 #define lson cur<<1
  5 #define rson cur<<1|1
  6 using namespace std;
  7 typedef long long LL;
  8 const int maxn = 200000 + 5;
  9 const int root = 1;
 10 struct seg            //扫描线结构体
 11 {
 12     int x, y1, y2; //扫描线数据  x横坐标  y1,y2,上下顶点
 13     short flag;       //标记是进入的还是出来的(对于一个矩形所产生的两条扫描线来说)
 14     seg() {};
 15     seg(int a, int b, int c, short d):x(a), y1(b), y2(c), flag(d) {}
 16     inline friend bool operator <(seg a, seg b)
 17     {
 18         return a.x < b.x;    //用于sort
 19     }
 20 } ss[maxn];
 21 int m;               //扫描线总数
 22 int y[maxn];    //离散值-->实际值
 23 struct node               //线段树结构体 (加入的是扫描线(纵向))
 24 {
 25     int l, r, cover;      //左右范围(实际上没有用),cover:是否完全覆盖
 26     int yl, yr, len;   //实际范围和长度
 27     node() {}
 28     node(int a, int b, int c, int d, short f, int g)
 29     {
 30         l = a, r = b, yl = c, yr = d, cover = f, len = g;
 31     }
 32 } a[maxn << 2];
 33 inline void build(int cur, int l, int r)       //建立线段树
 34 {
 35     a[cur] = node(l, r, y[l], y[r], 0, 0);
 36     if (l+1 == r) return ;
 37     int mid = (l+r) >> 1;
 38     build(lson, l, mid);
 39     build(rson, mid, r);
 40 }
 41  
 42 inline void pushup(int cur)                          //计算当前cur结点覆盖的长度(纵向)
 43 {
 44     if (a[cur].cover > 0) a[cur].len = a[cur].yr - a[cur].yl;  //当前结点被完全覆盖
 45     else if (a[cur].l+1 == a[cur].r) a[cur].len = 0; //叶节点但已经被去除掉了(cover<=0)
 46     else  a[cur].len = a[lson].len + a[rson].len;    //自身未被完全覆盖,向子节点求助
 47 }
 48  
 49 inline void updata(int cur, seg b)                  //更新i.e加入边操作
 50 {
 51     if (b.y1 == a[cur].yl && b.y2 == a[cur].yr)
 52     {
 53         //被加入的边完全覆盖
 54         a[cur].cover += b.flag;                     //是否被抛弃
 55         pushup(cur);                                //计算长度
 56         return;
 57     }
 58     if (b.y2 <= a[rson].yl) updata(lson, b);
 59     else if (b.y1 >= a[lson].yr) updata(rson, b);
 60     else
 61     {
 62         seg tmp = b;                                //将b拆开付给lson rson
 63         tmp.y2 = a[lson].yr;
 64         updata(lson, tmp);
 65         tmp = b, tmp.y1 = a[rson].yl;
 66         updata(rson, tmp);
 67     }
 68     pushup(cur);
 69     return;
 70 }
 71 int main()
 72 {
 73     int t, n;
 74     int x1, x2, y1, y2;
 75     LL area;
 76     cin >> t;
 77     while(t--)
 78     {
 79         m = 0;
 80         scanf("%d", &n);
 81         area = 0;
 82         for (int i = 1; i <= n; i ++)
 83         {
 84             scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
 85             area += (LL)(x2 - x1) * (LL)(y2 - y1);
 86             ss[++m] = seg(x1, y1, y2, 1), y[m] = y1;            //建立扫描线
 87             ss[++m] = seg(x2, y1, y2, -1), y[m] = y2;
 88         }
 89         if(area < 0 || area > 1000000000000000000ll)
 90         {
 91             cout << "Bad" << endl;
 92             continue;
 93         }
 94         sort(ss+1,ss+1+m);
 95         sort(y+1,y+1+m);          //离散化
 96  
 97         build(root, 1, m);                                                //建树
 98         LL sum(0);
 99         for (int i = 1; i < m; i++)                                    //依次加边
100         {
101             updata(root, ss[i]);
102             sum += (LL)a[root].len * (LL)(ss[i+1].x - ss[i].x);   //计算此时面积
103         }
104         if(area == sum)
105             puts("Good");
106         else
107             puts("Bad");
108     }
109     return 0;
110 }
View Code

 

posted @ 2013-05-24 18:50  芒果布丁  阅读(185)  评论(0编辑  收藏  举报