zoukankan      html  css  js  c++  java
  • Hdu 1255

    题目链接

    覆盖的面积

    Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
    Total Submission(s): 3545    Accepted Submission(s): 1739


    Problem Description
    给定平面上若干矩形,求出被这些矩形覆盖过至少两次的区域的面积.

    Input
    输入数据的第一行是一个正整数T(1<=T<=100),代表测试数据的数量.每个测试数据的第一行是一个正整数N(1<=N<=1000),代表矩形的数量,然后是N行数据,每一行包含四个浮点数,代表平面上的一个矩形的左上角坐标和右下角坐标,矩形的上下边和X轴平行,左右边和Y轴平行.坐标的范围从0到100000.

    注意:本题的输入数据较多,推荐使用scanf读入数据.
    Output
    对于每组测试数据,请计算出被这些矩形覆盖过至少两次的区域的面积.结果保留两位小数.
    Sample Input
    2 5 1 1 4 2 1 3 3 7 2 1.5 5 4.5 3.5 1.25 7.5 4 6 3 10 7 3 0 0 1 1 1 0 2 1 2 0 3 1
    Sample Output
    7.63 0.00
    计算被两个及以上矩形覆盖的面积和。
    此种类型题目有两种做法。
    第一种效率较低:
    Accepted Code:
      1 /*************************************************************************
      2     > File Name: G.cpp
      3     > Author: Stomach_ache
      4     > Mail: sudaweitong@gmail.com
      5     > Created Time: 2014年07月26日 星期六 19时05分05秒
      6     > Propose: hdu 1542
      7  ************************************************************************/
      8 #include <cmath>
      9 #include <string>
     10 #include <cstdio>
     11 #include <fstream>
     12 #include <cstring>
     13 #include <iostream>
     14 #include <algorithm>
     15 using namespace std;
     16 
     17 const int maxn = 1100;
     18 struct Line {
     19       double x, y1, y2;
     20     int cover;
     21     friend bool operator < (Line a, Line b) {
     22           return a.x < b.x;
     23     }
     24 }line[maxn*2 + 5];
     25 
     26 struct node {
     27       double x, y1, y2;
     28     int cover, flag;
     29 }Tree[maxn*1000];
     30 int n;
     31 double y[maxn*2];
     32 
     33 void build(int root, int L, int R) {
     34       Tree[root].x = -1;
     35       Tree[root].cover = 0;
     36     Tree[root].y1 = y[L];
     37     Tree[root].y2 = y[R];
     38     Tree[root].flag = 0;
     39       if (R - L == 1) {
     40           Tree[root].flag = 1;
     41         return ;
     42     }
     43     int M = (L + R) / 2;
     44     build(root * 2, L, M);
     45     build(root * 2 + 1, M, R);
     46 }
     47 
     48 double insert(int root, Line &ll) {
     49       if (Tree[root].y1 >= ll.y2 || Tree[root].y2 <= ll.y1) {
     50           return 0.0;
     51     }
     52     if (Tree[root].flag) {
     53           if (Tree[root].cover > 1) {
     54             double ans = (ll.x - Tree[root].x) * (Tree[root].y2 - Tree[root].y1);
     55             Tree[root].x = ll.x;
     56               Tree[root].cover += ll.cover;
     57             return ans;
     58         } else {
     59               Tree[root].cover += ll.cover;
     60             Tree[root].x = ll.x;
     61             return 0.0;
     62         }
     63     }
     64     double ans1 = insert(root * 2, ll);
     65     double ans2 = insert(root * 2 + 1, ll);
     66     return ans1 + ans2;
     67 }
     68 
     69 int main(void) {
     70 #ifndef ONLINE_JUDGE
     71       freopen("in.txt", "r", stdin);
     72 #endif
     73       int cas;
     74     scanf("%d", &cas);
     75       while (cas--) {
     76         scanf("%d", &n); 
     77           int cnt = 0;
     78           for (int i = 0; i < n; i++) {
     79              double xx, yy, xxx, yyy;
     80             scanf("%lf %lf %lf %lf", &xx, &yy, &xxx, &yyy);
     81             y[++cnt] = yy;
     82             line[cnt].x = xx; line[cnt].y1 = yy; line[cnt].y2 = yyy;
     83             line[cnt].cover = 1;
     84             y[++cnt] = yyy;
     85             line[cnt].x = xxx; line[cnt].y1 = yy; line[cnt].y2 = yyy;
     86             line[cnt].cover = -1;
     87         }
     88         sort(y + 1, y + cnt + 1);
     89         int len = 1;
     90         for (int i = 2; i <= cnt; i++) {
     91               if (y[i] != y[len]) {
     92                   y[++len] = y[i];
     93             }
     94         }
     95         sort(line + 1, line + cnt + 1);
     96         build(1, 1, len);
     97         double ans = 0.0;
     98         for (int i = 1; i <= cnt; i++) {
     99               ans += insert(1, line[i]);
    100         }
    101         printf("%.2f
    ", ans);
    102     }
    103 
    104     return 0;
    105 }

    第二种做法效率较高。

    Accepted Code:
      1 /*************************************************************************
      2     > File Name: G.cpp
      3     > Author: Stomach_ache
      4     > Mail: sudaweitong@gmail.com
      5     > Created Time: 2014年07月26日 星期六 19时05分05秒
      6     > Propose: hdu 
      7  ************************************************************************/
      8 #include <map>
      9 #include <cmath>
     10 #include <string>
     11 #include <cstdio>
     12 #include <vector>
     13 #include <fstream>
     14 #include <cstring>
     15 #include <iostream>
     16 #include <algorithm>
     17 using namespace std;
     18 
     19 const int maxn = 1100;
     20 //保存每条线段的信息
     21 struct Line {
     22       double x, y1, y2;
     23     //矩形的左边或者右边
     24     int flag;
     25     friend bool operator < (Line a, Line b) {
     26           return a.x < b.x;
     27     }
     28 }line[maxn*2 + 5];
     29 
     30 //线段树结点信息
     31 struct node {
     32       int l, r;
     33     //线段被覆盖的次数
     34     int cover;
     35     //len为被覆盖一次的长度,len2为被覆盖两次的长度
     36     double len, len2;
     37 }Tree[maxn*40];
     38 int n;
     39 //保存所有y轴坐标
     40 double y[maxn*2];
     41 //离散化使用
     42 vector<double> xs;
     43 
     44 void build(int root, int L, int R) {
     45       Tree[root].l = L;
     46     Tree[root].r = R;
     47       Tree[root].len = 0.0;
     48     Tree[root].len2 = 0.0;
     49       Tree[root].cover = 0;
     50       if (R - L == 1) {
     51         return ;
     52     }
     53     int M = (L + R) / 2;
     54     build(root * 2, L, M);
     55     build(root * 2 + 1, M, R);
     56 }
     57 
     58 void pushup(int root) {
     59       //被覆盖两次以上
     60     if (Tree[root].cover > 1) {
     61           Tree[root].len = 0;
     62           Tree[root].len2 = xs[Tree[root].r-1] - xs[Tree[root].l-1];
     63     } else if (Tree[root].cover == 1) { //被覆盖一次
     64         Tree[root].len2 = Tree[root*2].len + Tree[root*2+1].len
     65                            +Tree[root*2].len2 + Tree[root*2+1].len2;
     66           Tree[root].len = xs[Tree[root].r-1] - xs[Tree[root].l-1]
     67                            - Tree[root].len2;
     68     } else { //没有被覆盖
     69          if (Tree[root].l + 1 == Tree[root].r)
     70             Tree[root].len = Tree[root].len2 = 0.0;
     71         else {
     72             Tree[root].len = Tree[root*2].len + Tree[root*2+1].len;
     73             Tree[root].len2 = Tree[root*2].len2 + Tree[root*2+1].len2;
     74         }
     75     }
     76 }
     77 
     78 void update(int root, int L, int R, int flag) {
     79       //不在当前区间内
     80       if (Tree[root].l >= R || Tree[root].r <= L) 
     81           return ;
     82     //包含在当前区间内
     83       if (Tree[root].l >= L && Tree[root].r <= R) {
     84         Tree[root].cover += flag;
     85           pushup(root);
     86           return ;
     87     }
     88     int M = (Tree[root].l + Tree[root].r) / 2;
     89     update(root*2, L, R, flag);
     90     update(root*2+1, L, R, flag);
     91     pushup(root);
     92 }
     93 
     94 //离散化
     95 int compress(int m) {
     96       xs.clear();
     97     for (int i = 1; i <= m; i++) xs.push_back(y[i]);
     98     sort(xs.begin(), xs.end());
     99     xs.erase(unique(xs.begin(), xs.end()), xs.end());
    100     return xs.size();
    101 }
    102 
    103 
    104 int main(void) {
    105 #ifndef ONLINE_JUDGE
    106       freopen("in.txt", "r", stdin);
    107 #endif
    108       int cas;
    109     scanf("%d", &cas);
    110       while (cas--) {
    111           scanf("%d", &n);
    112           int cnt = 0;
    113           for (int i = 0; i < n; i++) {
    114              double xx, yy, xxx, yyy;
    115             scanf("%lf %lf %lf %lf", &xx, &yy, &xxx, &yyy);
    116             y[++cnt] = yy;
    117             line[cnt].x = xx; line[cnt].y1 = yy; line[cnt].y2 = yyy;
    118             line[cnt].flag = 1;
    119             y[++cnt] = yyy;
    120             line[cnt].x = xxx; line[cnt].y1 = yy; line[cnt].y2 = yyy;
    121             line[cnt].flag = -1;
    122         }
    123         int w = compress(cnt);
    124         sort(line + 1, line + cnt + 1);
    125         build(1, 1, cnt);
    126         double ans = 0.0;
    127         int l = find(xs.begin(), xs.end(), line[1].y1) - xs.begin() + 1;
    128         int r = find(xs.begin(), xs.end(), line[1].y2) - xs.begin() + 1;
    129         update(1, l, r, line[1].flag);
    130         for (int i = 2; i <= cnt; i++) {
    131               int l = find(xs.begin(), xs.end(), line[i].y1) - xs.begin() + 1;
    132             int r = find(xs.begin(), xs.end(), line[i].y2) - xs.begin() + 1;
    133             ans += (line[i].x - line[i-1].x) * Tree[1].len2;
    134               update(1, l, r, line[i].flag);
    135         }
    136         printf("%.2f
    ", ans);
    137     }
    138 
    139     return 0;
    140 }
  • 相关阅读:
    Hdu 4496 D-City
    Hdu 1213 How Many Tables
    T1387:搭配购买(buy)
    codevs 2597 团伙
    Hdu 1232 畅通工程
    RQNOJ PID331 家族
    提高组day4
    xjoi2018提高组训训练25
    关于upp和lower
    矩阵快速幂求fib
  • 原文地址:https://www.cnblogs.com/Stomach-ache/p/3871741.html
Copyright © 2011-2022 走看看