• poj 1177 Picture (线段树 扫描线 离散化 矩形周长并)


    题目链接

    题意:给出n个矩形,每个矩形给左下 和 右上的坐标,求围成的周长的长度。

    分析:

    首先感谢大神的博客,最近做题经常看大神的博客:http://www.cnblogs.com/kuangbin/

    沿x轴离散化。和之前的矩阵面积并有点像。

    但是一定要去重,否则会错

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <vector>
      4 #include <cstring>
      5 #include <cstdlib>
      6 #include <algorithm>
      7 #define LL __int64
      8 #define lson l, mid, 2*rt
      9 #define rson mid+1, r, 2*rt+1
     10 const int maxn = 10000+10;
     11 using namespace std;
     12 int n, x[maxn];
     13 struct node
     14 {
     15     int l, r, cnt;
     16     int lf, rf;
     17     int num, c; //num是分支的个数,即当前的x段有多少段,可以想象一段是对应两个竖边的。
     18     bool lc, rc;  //表示左端是否覆盖,和右端是否覆盖,用来判断x段是否练成一块了
     19 }tr[maxn*4];
     20 struct Line
     21 {
     22     int y, x1, x2, f;
     23 }line[maxn];
     24 bool cmp(Line a, Line b)
     25 {
     26     return a.y < b.y;
     27 }
     28 void build(int l, int r, int rt)
     29 {
     30     tr[rt].l = l; tr[rt].r = r;
     31     tr[rt].lf = x[l]; tr[rt].rf = x[r];
     32     tr[rt].cnt = 0; tr[rt].num = 0;
     33     tr[rt].c = 0;
     34     tr[rt].lc = tr[rt].rc = false;
     35     if(tr[rt].l+1 == tr[rt].r) return;
     36     int mid = (l+r)/2;
     37     build(l, mid, 2*rt);
     38     build(mid, r, 2*rt+1);
     39 }
     40 void calen(int rt)
     41 {
     42     if(tr[rt].c>0)
     43     {
     44         tr[rt].cnt = tr[rt].rf-tr[rt].lf;
     45         tr[rt].num = 1;
     46         tr[rt].lc = tr[rt].rc = true;  //这整个一块都覆盖了,左右端点自然也覆盖
     47         return;
     48     }
     49     if(tr[rt].l+1 == tr[rt].r)
     50     {
     51         tr[rt].cnt = tr[rt].num = 0;
     52         tr[rt].lc = tr[rt].rc = false;
     53     }
     54     else
     55     {
     56         tr[rt].cnt = tr[2*rt].cnt+tr[2*rt+1].cnt;
     57         tr[rt].lc = tr[2*rt].lc;  tr[rt].rc = tr[2*rt+1].rc;//自己这块没有覆盖,看一下子节点是否有覆盖
     58         tr[rt].num = tr[2*rt].num+tr[2*rt+1].num;
     59         if(tr[2*rt].rc && tr[2*rt+1].lc) tr[rt].num --;  //如果当前这个节点的子节点左的右
     60                         //覆盖和右的左覆盖说明中间已经练成一片了,所以分支-1
     61     }
     62 }
     63 void update(int rt, Line e)
     64 {
     65     if(tr[rt].lf==e.x1 && tr[rt].rf==e.x2)
     66     {
     67         tr[rt].c += e.f;
     68         calen(rt);
     69         return;
     70     }
     71     if(e.x2<=tr[2*rt].rf) update(2*rt, e);
     72     else if(e.x1>=tr[2*rt+1].lf) update(2*rt+1, e);
     73     else
     74     {
     75         Line tmp;
     76         tmp = e;
     77         tmp.x2 = tr[2*rt].rf;
     78         update(2*rt, tmp);
     79         tmp = e;
     80         tmp.x1 = tr[2*rt+1].lf;
     81         update(2*rt+1, tmp);
     82     }
     83     calen(rt);
     84 }
     85 int main()
     86 {
     87     int i, t, ans, pre;
     88     int x1, x2, y1, y2;
     89     while(~scanf("%d", &n))
     90     {
     91         t = 0; ans = 0; pre = 0;
     92         for(i = 0; i < n; i++)
     93         {
     94             scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
     95             line[t].x1 = x1; line[t].x2 = x2;
     96             line[t].y = y1; line[t].f = 1;
     97             x[t++] = x1;
     98             line[t].x1 = x1; line[t].x2 = x2;
     99             line[t].y = y2; line[t].f = -1;
    100             x[t++] = x2;
    101         }
    102         sort(x, x+t);
    103         sort(line, line+t, cmp);
    104         int y = unique(x, x+t)-x;  //去重
    105         build(0, y-1, 1);
    106 
    107         for(i = 0; i < t-1; i++)
    108         {
    109             update(1, line[i]);
    110             ans += tr[1].num*2*(line[i+1].y-line[i].y); //竖线的长度
    111             ans += abs(tr[1].cnt-pre); //加上 新增的横线 或者 是减少的横线
    112             pre = tr[1].cnt;
    113         }
    114         update(1, line[i]);
    115         ans += abs(tr[1].cnt-pre);
    116         printf("%d
    ", ans);
    117     }
    118     return 0;
    119 }
  • 相关阅读:
    js 中的 EventLoop
    线程的并发工具类
    xpath获取某个节点下的全部字节点的文本
    2020中国 .NET开发者大会精彩回顾:葡萄城高性能表格技术解读
    .NET 控件集 ComponentOne V2020.0 Update3 发布,正式支持 .NET 5
    log4net配置
    TP5.1 爬虫
    pip下载慢
    TP5.1 二维码生成
    composer插件集合
  • 原文地址:https://www.cnblogs.com/bfshm/p/3903432.html
Copyright © 2020-2023  润新知