hdu 1542&poj 1151 Atlantis線分ツリー走査線矩形面積を求め

15181 ワード

タイトルリンク:http://acm.hdu.edu.cn/showproblem.php?pid=1542
題意:n個の矩形を与えて、矩形の面積を求めてそして.
考え方:古典的な走査線法で矩形面積を求めます.座標が大きいため、横座標を離散化するか、縦座標を離散化するかを選択できます.
横座標を離散化すると、各長方形の上下2つの線分の左の始点、右の始点と高さ、および上または下のエッジが記録されます.
下から上へスキャンを選択すると、矩形の下辺を1に記録し、矩形の上辺を-1に記録します.
これらのセグメントを高さhで小さいものから大きいものに並べ替え、下から上へ走査し、毎回直線に遭遇し、下の場合、セグメントツリーの対応する区間+1になる.
上の場合、セグメントツリーの対応する区間-1です.次に、全区間が上書きされた長さを更新し、その長さ*(現在走査されている直線と次の直線の高さ差)を毎回加算します.
図を描くとはっきりします.
  1 #include 
  2 using namespace std;
  3 int n;
  4 #define maxn 210
  5 #define lson l, m, rt<<1
  6 #define rson m+1, r, rt<<1|1
  7 struct Line
  8 {
  9     double l, r, h;
 10     int mark;
 11 }line[maxn];
 12 double a[maxn], b[maxn];
 13 map <int, double> mp;
 14 int cnt;
 15 bool cmp(Line l1, Line l2)
 16 {
 17     return l1.h < l2.h;
 18 }
 19 int sum[maxn<<2];
 20 double cover[maxn<<2];
 21 void pushup(int l, int r, int rt)
 22 {
 23     if(sum[rt]) cover[rt] = mp[r+1] - mp[l];
 24     else
 25     {
 26         if(r == l) cover[rt] = 0;
 27         else cover[rt] = cover[rt<<1] + cover[rt<<1|1];
 28     }
 29 }
 30 void build(int l, int r, int rt)
 31 {
 32     cover[rt] = 0; sum[rt] = 0;
 33     if(l == r) return;
 34     int m = (l+r)>>1;
 35     build(lson);
 36     build(rson);
 37     pushup(l, r, rt);
 38 }
 39 void update(int L, int R, int val, int l, int r, int rt)
 40 {
 41     if(L == l && R == r)
 42     {
 43         sum[rt] += val;
 44         pushup(l, r, rt);
 45         return;
 46     }
 47     int m = (l+r)>>1;
 48     if(R <= m) update(L, R, val, lson);
 49     else if(L > m) update(L, R, val, rson);
 50     else
 51     {
 52         update(L, m, val, lson);
 53         update(m+1, R, val, rson);
 54     }
 55     pushup(l, r, rt);
 56 }
 57 int main() 
 58 {
 59     //freopen("in.txt", "r", stdin);
 60     //freopen("out.txt", "w", stdout);
 61     int cast = 0;
 62     while(~scanf("%d", &n) && n)
 63     {
 64         cnt = 0; mp.clear();
 65         for(int i = 1; i <= n; i++)
 66         {
 67             double x1, y1, x2, y2;
 68             scanf("%lf%lf%lf%lf", &x1, &y1, &x2, &y2);
 69             a[cnt++] = x1; a[cnt++] = x2;
 70             
 71             line[i*2-1].l = x1; line[i*2-1].r = x2;    //  
 72             line[i*2-1].h = y1; line[i*2-1].mark = 1; 
 73             
 74             line[i*2].l = x1; line[i*2].r = x2;
 75             line[i*2].h = y2; line[i*2].mark = -1;     //  
 76         }
 77         for(int i = 0; i < cnt; i++) b[i] = a[i];
 78         sort(a, a+cnt);
 79         int precnt = cnt;
 80         cnt = unique(a, a+cnt) - a;
 81         
 82         for(int i = 0; i < precnt; i++)
 83         {
 84             mp[lower_bound(a, a+cnt, b[i]) - a + 1] = b[i];
 85         }
 86         sort(line+1, line+1+2*n, cmp);
 87         
 88         build(1, cnt, 1);
 89         double ans = 0;
 90         for(int i = 1; i <= 2*n; i++)
 91         {
 92             int ll = lower_bound(a, a+cnt, line[i].l) - a + 1;
 93             int rr = lower_bound(a, a+cnt, line[i].r) - a + 1;
 94             update(ll, rr-1, line[i].mark, 1, cnt, 1); 
 95             if(i != 2*n) ans += cover[1]*(line[i+1].h - line[i].h); 
 96         }
 97         cast++; printf("Test case #%d
", cast); 98 printf("Total explored area: %.2f

", ans); 99 100 } 101 return 0; 102 }

 
転載先:https://www.cnblogs.com/titicia/p/5528544.html