zoukankan      html  css  js  c++  java
  • POJ 1151 Atlantis 线段树+离散化

    题目链接http://poj.org/problem?id=1151  http://acm.hdu.edu.cn/showproblem.php?pid=1542

    题目大意:给你几个矩形的坐标,求他们的面积的并。

    解题思路:可以参考http://www.cnblogs.com/kuangbin/archive/2011/08/16/2140544.html,实际上就是一个方向直接算出,另一个方向使用线段树维护已经覆盖的底边的长度。具体操作不算复杂:假想一条扫描下从下往上开始进行扫描,初始时候没有边,线段树维护的值为0,每次碰到一条底边,就将这条底边加入线段树中并且更新他们覆盖的总长度,如果碰到顶边,就将这个边从线段树中删除,而总面积即是每两条边之间的面积的总和。

    给每条底边设置个flag = 1,顶边flag = -1,那么就容易在线段树上操作了。

    离散化实际上是对每个浮点数坐标离散化。注意的是离散后,线段树上的中值mid既可以在左孩子又可以在右孩子中。

    代码:

     1 const int maxn = 250;
     2 struct node{
     3     int f;
     4     double rlen, rl, rr;
     5 };
     6 node tree[maxn * 4];
     7 struct Line{
     8     double x1, x2, y;
     9     int flag;
    10     bool operator < (const Line &t) const{
    11         return y < t.y;
    12     }
    13     Line() {}
    14     Line(double a, double b, double c, int f): x1(a), x2(b), y(c), flag(f) {}
    15 };
    16 Line lines[maxn];
    17 double ys[maxn];
    18 int n;
    19 
    20 void build(int l, int r, int k){
    21     tree[k].f = 0; tree[k].rl = ys[l]; tree[k].rr = ys[r]; tree[k].rlen = 0;
    22     if(l + 1 == r) return;
    23     int mid = (l + r) >> 1, lc = k << 1, rc = k << 1 | 1;
    24     build(l, mid, lc);
    25     build(mid, r, rc);
    26 }
    27 void cacu(int l, int r, int k){
    28     if(tree[k].f > 0) {
    29         tree[k].rlen = tree[k].rr - tree[k].rl;
    30         return;
    31     }
    32     if(l + 1 == r) tree[k].rlen = 0;
    33     else tree[k].rlen = tree[k << 1].rlen + tree[k << 1 | 1].rlen;
    34 } 
    35 void update(Line ul, int l, int r, int k){
    36     if(ul.x1 <= tree[k].rl && ul.x2 >= tree[k].rr){
    37         tree[k].f += ul.flag;
    38         cacu(l, r, k);
    39         return;
    40     }
    41     if(ul.x1 > tree[k].rr || ul.x2 < tree[k].rl) return;
    42     int mid = (l + r) >> 1, lc = k << 1, rc = k << 1 | 1;
    43     if(ul.x2 <= tree[lc].rr) update(ul, l, mid, lc);
    44     else if(ul.x1 >= tree[rc].rl) update(ul, mid, r, rc);
    45     else{
    46         update(ul, l, mid, lc);
    47         update(ul, mid, r, rc);
    48     }
    49     cacu(l, r, k);
    50 }
    51 
    52 int main(){
    53     int t = 1;
    54     while(scanf("%d", &n) != EOF && n != 0){
    55         int cnt = 1;
    56         for(int i = 1; i <= n; i++){
    57             double x1, x2, y1, y2;
    58             scanf("%lf %lf %lf %lf", &x1, &y1, &x2, &y2);
    59             lines[cnt] = Line(x1, x2, y1, 1);
    60             ys[cnt] = x1; cnt++;
    61             lines[cnt] = Line(x1, x2, y2, -1);
    62             ys[cnt] = x2; cnt++;
    63         }
    64         sort(lines + 1, lines + cnt);
    65         sort(ys + 1, ys + cnt);
    66         cnt--;
    67         build(1, cnt, 1);
    68         update(lines[1], 1, cnt, 1);
    69         double area = 0;
    70         for(int i = 2; i <= cnt; i++){
    71             area += (lines[i].y - lines[i - 1].y) * tree[1].rlen;
    72             update(lines[i], 1, cnt, 1);
    73         }
    74         printf("Test case #%d
    Total explored area: ", t++);
    75         printf("%.2f
    
    ", area);
    76     }
    77 }

    题目:

    Atlantis
    Time Limit: 1000MS   Memory Limit: 10000K
    Total Submissions: 23249   Accepted: 8669

    Description

    There are several ancient Greek texts that contain descriptions of the fabled island Atlantis. Some of these texts even include maps of parts of the island. But unfortunately, these maps describe different regions of Atlantis. Your friend Bill has to know the total area for which maps exist. You (unwisely) volunteered to write a program that calculates this quantity.

    Input

    The input consists of several test cases. Each test case starts with a line containing a single integer n (1 <= n <= 100) of available maps. The n following lines describe one map each. Each of these lines contains four numbers x1;y1;x2;y2 (0 <= x1 < x2 <= 100000;0 <= y1 < y2 <= 100000), not necessarily integers. The values (x1; y1) and (x2;y2) are the coordinates of the top-left resp. bottom-right corner of the mapped area. 
    The input file is terminated by a line containing a single 0. Don't process it.

    Output

    For each test case, your program should output one section. The first line of each section must be "Test case #k", where k is the number of the test case (starting with 1). The second one must be "Total explored area: a", where a is the total explored area (i.e. the area of the union of all rectangles in this test case), printed exact to two digits to the right of the decimal point. 
    Output a blank line after each test case.

    Sample Input

    2
    10 10 20 20
    15 15 25 25.5
    0

    Sample Output

    Test case #1
    Total explored area: 180.00 

    Source

  • 相关阅读:
    手游产品经理初探(十)竞品分析
    Openfire开发配置,Openfire源码配置,OpenFire二次开发配置
    code forces 148D Bag of mice (概率DP)
    Android Studio怎样更改JDK和SDK的路径?
    bbb
    收集了三年的最好的设计站点
    C# foreach 有用方法具体解释
    Java 过滤器的作用
    SVD神秘值分解
    《C语言编写 学生成绩管理系统》
  • 原文地址:https://www.cnblogs.com/bolderic/p/7323268.html
Copyright © 2011-2022 走看看