Poj--1151(线段树,离散化,扫描线)

2014-09-24 22:35:43

思路:经典的线段树+扫描线,由于数据较大,所以要离散化。需要注意的是建树过程中:叶子节点是长度为1的单元区间,然后相邻叶节点有重合点(思考为什么)

    参考了众巨的博客,最后感觉是默了下来,看来还得再刷几道类似题才能真正懂。Orz。

  1 /*************************************************************************
  2     > File Name: p1151.cpp
  3     > Author: Nature
  4     > Mail: 564374850@qq.com
  5     > Created Time: Wed 24 Sep 2014 09:53:10 PM CST
  6 ************************************************************************/
  7 
  8 #include <cstdio>
  9 #include <cstring>
 10 #include <cstdlib>
 11 #include <cmath>
 12 #include <vector>
 13 #include <queue>
 14 #include <iostream>
 15 #include <algorithm>
 16 using namespace std;
 17 typedef long long ll;
 18 const int INF = 1 << 29;
 19 const int maxn = 205;
 20 
 21 struct Edge{
 22     int flag;
 23     double x,y1,y2;
 24     friend bool operator < (Edge a,Edge b){
 25         return a.x < b.x;
 26     }
 27 }e[maxn];
 28 struct node{
 29     int l,r;
 30     double tl,tr,len;
 31     int cover;
 32 }a[maxn << 2];
 33 int n;
 34 double y[maxn];
 35 
 36 void Build_tree(int pos,int l,int r){
 37     a[pos].l = l;
 38     a[pos].r = r;
 39     a[pos].tl = y[l];
 40     a[pos].tr = y[r];
 41     a[pos].cover = a[pos].len = 0;
 42     if(l + 1 == r)
 43         return;
 44     int mid = l + (r - l) / 2;
 45     Build_tree(pos << 1,l,mid);
 46     Build_tree(pos << 1 | 1,mid,r);
 47 }
 48 
 49 void Cal_len(int pos){
 50     if(a[pos].cover > 0)
 51         a[pos].len = a[pos].tr - a[pos].tl;
 52     else if(a[pos].l + 1 == a[pos].r)
 53         a[pos].len = 0;
 54     else
 55         a[pos].len = a[pos << 1].len + a[pos << 1 | 1].len;
 56 }
 57 
 58 void Update(int pos,int l,int r,Edge t){
 59     if(a[pos].tl == t.y1 && a[pos].tr == t.y2){
 60         a[pos].cover += t.flag;
 61         Cal_len(pos);
 62         return;
 63     }
 64     int mid = l + (r - l) / 2;
 65     if(t.y2 <= a[pos << 1 | 1].tl) Update(pos << 1,l,mid,t);
 66     else if(t.y1 >= a[pos << 1].tr) Update(pos << 1 | 1,mid,r,t);
 67     else{
 68         Edge tmp = t;
 69         tmp.y2 = a[pos << 1].tr;
 70         Update(pos << 1,l,mid,tmp);
 71         tmp.y2 = t.y2;
 72         tmp.y1 = a[pos << 1 | 1].tl;
 73         Update(pos << 1 | 1,mid,r,tmp);
 74     }
 75     Cal_len(pos);
 76 }
 77 
 78 int main(){
 79     int Case = 0;
 80     double x1,y1,x2,y2;
 81     while(scanf("%d",&n) != EOF && n){
 82         int c = 0;
 83         for(int i = 1; i <= n; ++i){
 84             scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
 85             e[++c].x = x1;
 86             e[c].y1 = y1;
 87             e[c].y2 = y2;
 88             e[c].flag = 1;
 89             y[c] = y1;
 90 
 91             e[++c].x = x2;
 92             e[c].y1 = y1;
 93             e[c].y2 = y2;
 94             e[c].flag = -1;
 95             y[c] = y2;
 96         }
 97         sort(e + 1,e + c + 1);
 98         sort(y + 1,y + c + 1);
 99         Build_tree(1,1,c);
100         Update(1,1,c,e[1]);
101         double ans = 0.0;
102         for(int i = 2; i <= c; ++i){
103             ans += a[1].len * (e[i].x - e[i - 1].x);
104             Update(1,1,c,e[i]);
105         }
106         printf("Test case #%d\n",++Case);
107         printf("Total explored area: %.2f\n\n",ans);
108     }
109     return 0;
110 }

 

posted @ 2014-09-24 22:38  Naturain  阅读(142)  评论(0)    收藏  举报