zoukankan      html  css  js  c++  java
  • POJ 1177 Picture

    题目链接http://poj.org/problem?id=1177

    题目大意:给出N个矩形坐标,问他们组成的图形的周长。包括内周长,外周长,以及不想交的区域的周长。

    解题思路:同样是扫面线法,本题使用的方法整体上与矩形面积并所使用的方法类似,但是细节上有所更改。

    具体过程:离散化,线段树维护X轴被覆盖的长度以及该区间的段数(不相连子区间数),初始状态未被覆盖。从下往上扫描,每次碰到矩形底边将其加入线段树,碰到顶边从线段树中删除。

    每扫描到一条线,更新线段树,之后,水平方向,ans加上 (线段树根节点长度值 - 上一次的长度 )的绝对值, 竖直方向,ans + 2 * 两条线间隔 * 线段树根节点区间段数。从右往左扫描的话同样。稍微思考一下即可知道这种方式是没问题的。

    结构上,线段树节点保存 l, r, 实际左端点, 实际右端点, 实际长度, 被线段全部覆盖数目 ,不相连段个数,左孩子是否被全覆盖,右孩子是否被全覆盖

    另外,离散化后需要去除相同元素。

    代码:

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

    题目:

    Picture
    Time Limit: 2000MS   Memory Limit: 10000K
    Total Submissions: 12728   Accepted: 6733

    Description

    A number of rectangular posters, photographs and other pictures of the same shape are pasted on a wall. Their sides are all vertical or horizontal. Each rectangle can be partially or totally covered by the others. The length of the boundary of the union of all rectangles is called the perimeter. 

    Write a program to calculate the perimeter. An example with 7 rectangles is shown in Figure 1. 

    The corresponding boundary is the whole set of line segments drawn in Figure 2. 

    The vertices of all rectangles have integer coordinates. 

    Input

    Your program is to read from standard input. The first line contains the number of rectangles pasted on the wall. In each of the subsequent lines, one can find the integer coordinates of the lower left vertex and the upper right vertex of each rectangle. The values of those coordinates are given as ordered pairs consisting of an x-coordinate followed by a y-coordinate. 

    0 <= number of rectangles < 5000 
    All coordinates are in the range [-10000,10000] and any existing rectangle has a positive area.

    Output

    Your program is to write to standard output. The output must contain a single line with a non-negative integer which corresponds to the perimeter for the input rectangles.

    Sample Input

    7
    -15 0 5 10
    -5 8 20 25
    15 -4 24 14
    0 -6 16 4
    2 15 10 22
    30 10 36 20
    34 0 40 16

    Sample Output

    228

    Source

  • 相关阅读:
    从零开始写自己的PHP框架系列教程[前言]
    从零开始写自己的PHP框架系列教程(二)[App.php]
    Nginx
    常见的CSS
    常用JS代码
    jq常用
    EMMET 的HTM自动生成
    JS的小判断
    ARM寄存器与ATPCS/AAPCS
    关于笔记本电脑随想
  • 原文地址:https://www.cnblogs.com/bolderic/p/7325579.html
Copyright © 2011-2022 走看看