HDU 1255 覆盖的面积 (扫描线 线段树 离散化 矩形面积并)

题目链接

题意:中文题意。

分析:纯手敲,与上一道题目很相似,但是刚开始我以为只是把cnt》=0改成cnt>=2就行了,、

但是后来发现当当前加入的线段的范围之前 还有线段的时候就不行了,因为虽然现在都不等于

2,但是之前的那个线段加上现在的已经覆盖2次了。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <vector>
  4 #include <cstring>
  5 #include <cstdlib>
  6 #include <algorithm>
  7 #define LL __int64
  8 #define lson l, mid, 2*rt
  9 #define rson mid+1, r, 2*rt+1
 10 const int maxn = 2000+10;
 11 using namespace std;
 12 int n;
 13 double y[maxn];
 14 struct node
 15 {
 16     int l, r, c;
 17     double cnt, lf, rf, more; //cnt还是代表覆盖的长度,增加了more代表两次及以上覆盖的长度
 18 }tr[4*maxn];
 19 struct Line
 20 {
 21     double x, y1, y2;
 22     int f;
 23 }line[maxn];
 24 bool cmp(Line a, Line b)
 25 {
 26     return a.x < b.x;
 27 }
 28 void build(int l, int r, int rt)
 29 {
 30     tr[rt].l = l; tr[rt].r = r;
 31     tr[rt].c = 0;  tr[rt].cnt = 0;
 32     tr[rt].more = 0;
 33     tr[rt].rf = y[r];  tr[rt].lf = y[l];
 34     if(l+1==r) return;
 35     int mid = (l+r)/2;
 36     build(l, mid, 2*rt);
 37     build(mid, r, 2*rt+1);
 38 }
 39 void calen(int rt)
 40 {
 41     if(tr[rt].c==0)
 42     {
 43         if(tr[rt].l+1==tr[rt].r)
 44         {
 45             tr[rt].cnt = 0; tr[rt].more = 0;
 46         }
 47         else
 48         {
 49             tr[rt].cnt = tr[2*rt].cnt+tr[2*rt+1].cnt;
 50             tr[rt].more = tr[2*rt].more+tr[2*rt+1].more;
 51         }
 52     }
 53     if(tr[rt].c==1)  //注意这一步是关键
 54     {
 55         tr[rt].cnt = tr[rt].rf-tr[rt].lf;
 56         if(tr[rt].l+1==tr[rt].r)  //因为没有注意是否到最后,错了一遍
 57         tr[rt].more = 0;
 58         else
 59         tr[rt].more = tr[2*rt].cnt + tr[2*rt+1].cnt; //为1的时候如果下面也有就加上
 60     }
 61     if(tr[rt].c>=2)
 62     {
 63         tr[rt].more = tr[rt].rf-tr[rt].lf;
 64         tr[rt].cnt = tr[rt].more;
 65     }
 66 }
 67 void update(int rt, Line e)
 68 {
 69     if(e.y1==tr[rt].lf && e.y2==tr[rt].rf)
 70     {
 71         tr[rt].c += e.f;
 72         calen(rt);
 73         return;
 74     }
 75     if(e.y2<=tr[2*rt].rf) update(2*rt, e);
 76     else if(e.y1>=tr[2*rt+1].lf) update(2*rt+1, e);
 77     else
 78     {
 79         Line tmp;
 80         tmp = e;
 81         tmp.y2 = tr[2*rt].rf; update(2*rt, tmp);
 82         tmp = e;
 83         tmp.y1 = tr[2*rt+1].lf; update(2*rt+1, tmp);
 84     }
 85     calen(rt);
 86 }
 87 int main()
 88 {
 89     int t, i, cnt;
 90     double x1, x2, y1, y2, ans;
 91     scanf("%d", &t);
 92     while(t--)
 93     {
 94         scanf("%d", &n);
 95         cnt = 1; ans = 0;
 96         for(i = 1; i <= n; i++)
 97         {
 98             scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
 99             line[cnt].x = x1; line[cnt].y1 = y1;
100             line[cnt].y2 = y2; line[cnt].f = 1;
101             y[cnt++] = y1;
102             line[cnt].x = x2; line[cnt].y1 = y1;
103             line[cnt].y2 = y2; line[cnt].f = -1;
104             y[cnt++] = y2;
105         }
106         sort(y+1, y+cnt);
107         sort(line+1, line+cnt, cmp);
108         cnt --;
109         build(1, cnt, 1);
110         update(1, line[1]);
111         for(i = 2; i <= cnt; i++)
112         {
113             ans += tr[1].more*(line[i].x - line[i-1].x);
114             update(1, line[i]);
115         }
116         printf("%.2lf\n", ans);
117     }
118     return 0;
119 }

 

posted @ 2014-08-09 16:50  水门  阅读(183)  评论(0编辑  收藏  举报